Skip to content

Instantly share code, notes, and snippets.

@bbrowning
Created December 17, 2012 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbrowning/4322061 to your computer and use it in GitHub Desktop.
Save bbrowning/4322061 to your computer and use it in GitHub Desktop.
Script to reproduce mongo ruby driver's runtime leak
bbrowning@bbrowning-mbp:~/tmp$ jruby mongo_leak.rb 2
Leaked 2 Ruby runtimes in RubyBSONCallback
Uncomment lines 15-16 of mongo_leak.rb and run again
bbrowning@bbrowning-mbp:~/tmp$ jruby mongo_leak.rb 2
Leaked 0 Ruby runtimes in RubyBSONCallback
Attached is a diff showing the same add_finalizer code from mongo_leak.rb but in Java for RubyBSONCallback.java
require 'mongo'
class Java::OrgJbson::RubyBSONCallback
field_reader :_runtimeCache
end
NUM_RUNTIMES = (ARGV[0] || 5).to_i
if java.lang.System.getProperty('checking_for_leaks') == 'true'
document = BSON.serialize(:hello => "world")
BSON.deserialize(document)
else
java.lang.System.setProperty('checking_for_leaks', 'true')
NUM_RUNTIMES.times do
runtime = org.jruby.Ruby.new_instance
runtime.load_service.require(__FILE__)
# runtime.add_finalizer {
# Java::OrgJbson.RubyBSONCallback._runtimeCache.remove(runtime)
# }
runtime.tear_down(false)
java.lang.System.gc
end
# A few more GCs for good measure
java.lang.System.gc
java.lang.System.gc
num_leaked = Java::OrgJbson.RubyBSONCallback._runtimeCache.size
puts "Leaked #{num_leaked} Ruby runtimes in RubyBSONCallback"
end
diff --git a/ext/jbson/src/main/jbson/RubyBSONCallback.java b/ext/jbson/src/main/jbson/RubyBSONCallback.java
index 5c12c27..f5ed7e0 100644
--- a/ext/jbson/src/main/jbson/RubyBSONCallback.java
+++ b/ext/jbson/src/main/jbson/RubyBSONCallback.java
@@ -320,7 +320,7 @@ public class RubyBSONCallback implements BSONCallback {
return _stack.size() < 1;
}
- private static HashMap<String, Object> _getRuntimeCache(Ruby runtime) {
+ private static HashMap<String, Object> _getRuntimeCache(final Ruby runtime) {
// each JRuby runtime may have different objects for these constants,
// so cache them separately for each runtime
@SuppressWarnings("unchecked")
@@ -329,6 +329,11 @@ public class RubyBSONCallback implements BSONCallback {
if(cache == null) {
cache = new HashMap<String, Object>();
_runtimeCache.put( runtime, cache );
+ runtime.addFinalizer( new Finalizable() {
+ public void finalize() {
+ _runtimeCache.remove( runtime );
+ }
+ } );
}
return cache;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment