-
-
Notifications
You must be signed in to change notification settings - Fork 933
Description
We are defining singleton methods on Java objects that had been freshly constructed. These objects get stored on the Java side, and then later retrieved again from the JRuby side, only to have their singleton methods missing. We are holding on to the original proxy from the constructed objects, so this shouldn't be a case of a garbage collected proxy object.
I started tracing JRuby with my scenario and found the code path I was hitting in ConstructorInvoker wasn't actually caching the JavaProxy in the ObjectProxyCache, while if I had gone through an InstanceMethodInvoker path, it would have been cached.
Below is a simple Minitest test case that fails, demonstrating the problem.
// Test.java
public class Test {
private static Test lastInstance;
public Test() {
lastInstance = this;
}
public static Test getLastInstance() {
return lastInstance;
}
}# test.rb
gem "minitest"
require "minitest/autorun"
Java::Default::Test.__persistent__ = true
class TestCaching < Minitest::Test
def test_constructed_proxy_is_cached
t = Java::Default::Test.new
def t.testing; 42; end
assert_equal 42, t.testing
assert_equal t, Java::Default::Test.last_instance
assert_equal 42, Java::Default::Test.last_instance.testing
end
endThe results of running on 1.7.22 and 9.0.4.0:
$ rvm jruby-1.7.22 do ruby test.rb
Run options: --seed 12875
# Running:
E
Finished in 0.006000s, 166.6667 runs/s, 333.3333 assertions/s.
1) Error:
TestCaching#test_constructed_proxy_is_cached:
NoMethodError: undefined method `testing' for #<Java::Default::Test:0x53fdffa1>
test.rb:11:in `test_constructed_proxy_is_cached'
1 runs, 2 assertions, 0 failures, 1 errors, 0 skips
$ rvm jruby-9.0.4.0 do ruby test.rb
Run options: --seed 9484
# Running:
E
Finished in 0.009849s, 101.5313 runs/s, 203.0626 assertions/s.
1) Error:
TestCaching#test_constructed_proxy_is_cached:
NoMethodError: undefined method `testing' for #<Java::Default::Test:0x1a78dacd>
test.rb:11:in `test_constructed_proxy_is_cached'
1 runs, 2 assertions, 0 failures, 1 errors, 0 skips
Some additional notes:
- In our codebase this works on
1.7.22, but this test fails in both (in our case, more is happening, so maybe that extra stuff is triggering a working path in1.7.22somehow) - If you drop
Java::Default::Test.__persistent__ = truefrom the test, it starts passing in9.0.4.0, but then if you create another test method that does the same thing, the second test fails (presumably the code triggering the warning about persistence is somehow getting the proxy object to be cached?)