Skip to content

Commit

Permalink
Fix memory leak in FFI usage from multiple runtimes
Browse files Browse the repository at this point in the history
This fixes JRUBY-5053 and GitHub issue jruby#203. Instead of storing the
AbstractInvoker refmap in a static Map, the same data is now stored on
an instance of the FFI class which holds all other per-runtime
FFI-related data.
  • Loading branch information
bbrowning authored and enebo committed Jun 12, 2012
1 parent cd0ca15 commit cfbb64d
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 11 deletions.
12 changes: 1 addition & 11 deletions src/org/jruby/ext/ffi/AbstractInvoker.java
Expand Up @@ -28,9 +28,6 @@

package org.jruby.ext.ffi;

import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
Expand All @@ -48,13 +45,6 @@
@JRubyClass(name = "FFI::" + AbstractInvoker.CLASS_NAME, parent = "Object")
public abstract class AbstractInvoker extends Pointer {
static final String CLASS_NAME = "AbstractInvoker";

/**
* Reference map to keep libraries open for as long as there is a method mapped
* to that library.
*/
private static final Map<DynamicMethod, AbstractInvoker> refmap
= Collections.synchronizedMap(new WeakHashMap<DynamicMethod, AbstractInvoker>());

/**
* The arity of this function.
Expand Down Expand Up @@ -94,7 +84,7 @@ public IRubyObject attach(ThreadContext context, IRubyObject obj, IRubyObject me
if (obj instanceof RubyModule) {
((RubyModule) obj).addMethod(methodName.asJavaString(), m);
}
refmap.put(m, this);
getRuntime().getFFI().registerAttachedMethod(m, this);

return this;
}
Expand Down
13 changes: 13 additions & 0 deletions src/org/jruby/ext/ffi/FFI.java
@@ -1,10 +1,12 @@
package org.jruby.ext.ffi;

import org.jruby.*;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;

/**
* The holder of all per-ruby-runtime FFI data
Expand All @@ -17,6 +19,13 @@ public class FFI {
public final RubyHash typedefs;
private final NullMemoryIO nullMemoryIO;
private final TypeSizeMapper sizeMapper;

/**
* Reference map to keep libraries open for as long as there is a method mapped
* to that library.
*/
private final Map<DynamicMethod, AbstractInvoker> refmap
= Collections.synchronizedMap(new WeakHashMap<DynamicMethod, AbstractInvoker>());


public FFI(RubyModule ffiModule) {
Expand All @@ -41,4 +50,8 @@ public TypeSizeMapper getSizeMapper() {
public NullMemoryIO getNullMemoryIO() {
return nullMemoryIO;
}

public void registerAttachedMethod(DynamicMethod method, AbstractInvoker invoker) {
refmap.put(method, invoker);
}
}

0 comments on commit cfbb64d

Please sign in to comment.