# WeakRef implementation for JRuby

**URL:** <https://www.ruby-forum.com/t/weakref-implementation-for-jruby/118558>\
**Category:** Ruby\
**Created:** [October 28, 2007, 9:32pm UTC](https://www.ruby-forum.com/t/weakref-implementation-for-jruby/118558 "2007-10-28T21:32:58Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![headius](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/7c8e57/32.png) [@headius](https://www.ruby-forum.com/u/headius)\
**Post date:** [October 28, 2007, 9:32pm UTC](https://www.ruby-forum.com/t/weakref-implementation-for-jruby/118558/1 "2007-10-28T21:32:58Z")

</div>

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(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
