Since this came up a few times, here's an example of implementing 
WeakRef in JRuby, using Java code. Obviously most of the heavy lifting 
is done by Java's WeakReference implementation.

I post this because I'm interested in hearing how this could be made 
easier. In my eyes, this is pretty clean, and far simpler to create a 
JRuby extension than a equivalent C extension...but I'm a Java guy. I'd 
love to know how this can be improved. Thoughts?

<<JAVA_CODE

//// All Ruby objects extend RubyObject in JRuby right now. That may 
change in the future to support objects in other branches of the class 
hierarchy.

public class WeakRef extends RubyObject {

//// The Java WeakReference object, pointing at a ruby object

     private WeakReference<IRubyObject> ref;

//// JRuby likes to have an allocator defined for all objects that have 
their own custom Java types. Here, we create an allocator for WeakRef

     private static final ObjectAllocator WEAKREF_ALLOCATOR = new 
ObjectAllocator() {
         public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
             return new WeakRef(runtime, klazz);
         }
     };

//// A requireable library must just implement Library. Here, we provide 
a static inner class to do that...then it's trivial to wire this up as 
an extension.
//// Note also this defines the WeakRef class as extending Delegator, 
and defines an Exception type for RefError.

     public static class WeakRefLibrary implements Library {
         public void load(Ruby runtime) throws IOException {
             RubyKernel.require(runtime.getKernel(), 
runtime.newString("delegate"), Block.NULL_BLOCK);

             RubyClass delegatorClass = 
(RubyClass)runtime.getClassFromPath("Delegator");
             RubyClass weakrefClass = runtime.defineClass("WeakRef", 
delegatorClass, WEAKREF_ALLOCATOR);

             weakrefClass.defineAnnotatedMethods(WeakRef.class);

             RubyClass referrorClass = runtime.defineClass("RefError", 
runtime.getStandardError(), runtime.getStandardError().getAllocator());
         }
     }

//// Standard constructor, pass in the JRuby runtime and the Ruby class 
this object has as its metaclass.

     public WeakRef(Ruby runtime, RubyClass klazz) {
         super(runtime, klazz);
     }

//// Here's the JRuby annotation for binding a method. This makes the 
Java method "getobj" bind to WeakRef as WeakRef#__getobj__

     @JRubyMethod(name = "__getobj__")
     public IRubyObject getobj() {
         IRubyObject obj = ref.get();

         if (obj == null) {
             // FIXME weakref.rb also does caller(2) here for the backtrace
             throw newRefError("Illegal Reference - probably recycled");
         }

         return obj;
     }

//// Another such binding for WeakRef::new.

     @JRubyMethod(name = "new", required = 1, meta = true)
     public static IRubyObject newInstance(IRubyObject clazz, 
IRubyObject arg) {
         WeakRef weakRef = (WeakRef)((RubyClass)clazz).allocate();

         weakRef.callInit(new IRubyObject[] {arg}, Block.NULL_BLOCK);

         return weakRef;
     }

//// And for WeakRef#initialize. Notice that it dispatches to the 
"super" implementation of initialize, which will call Delegator#initialize

     @JRubyMethod(name = "initialize", required = 1, frame = true, 
visibility = Visibility.PRIVATE)
     public IRubyObject initialize(IRubyObject obj) {
         ref = new WeakReference<IRubyObject>(obj);

         return callSuper(getRuntime().getCurrentContext(), new 
IRubyObject[] {obj}, Block.NULL_BLOCK);
     }

//// A binding for the weakref_alive? method

     @JRubyMethod(name = "weakref_alive?")
     public IRubyObject weakref_alive_p() {
         return ref.get() != null ? getRuntime().getTrue() : 
getRuntime().getFalse();
     }

//// And a utility method for constructing throwable RefError instances

     private RaiseException newRefError(String message) {
         RubyException exception =
 
(RubyException)getRuntime().getClass("RefError").newInstance(
                 new IRubyObject[] {getRuntime().newString(message)}, 
Block.NULL_BLOCK);

         return new RaiseException(exception);
     }
}

JAVA_CODE

- Charlie