Details
-
Type:
Bug
-
Status:
Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: JRuby 1.5.6
-
Fix Version/s: JRuby 1.6.4
-
Component/s: Java Integration
-
Labels:None
-
Environment:Mac OS X 10.6.5
Java(TM) SE Runtime Environment (build 1.6.0_22-b04-307-10M3261)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03-307, mixed mode)
JRuby 1.5.6
-
Number of attachments :
Description
Define a Java interface with a single-argument method named 'exec'. Define a Java class that defines a method that uses instances of that interface as a callback. Use JRuby to invoke the class's method using a block as its argument, attempting to take advantage of the closure conversion feature of JRuby.
When the callback is invoked by the Java method, rather than running the code defined in the block, the system attempts to coerce the argument to a String and Kernel.exec it. The same issue happens for any Kernel.* method name I've tried.
I'm a complete Ruby/JRuby noob, but based on a quick perusal of the code, it looks like closure conversion is implemented by defining method_missing on a fresh new RubyClass, and that any methods already defined for Ruby's Object are going to be invoked ahead of any interface methods with the same names. This behavior may be completely expected, then; if so, I apologize for the trouble.
I've attached example code illustrating the problem.
Your theory is probably correct; it's the first thought that came to mind for me as well. It does present a conundrum; obviously we'd like any interface to be convertible, regardless of whether the methods it defines already exist on converted object. So one approach would be to proactively define them to dispatch to the proc; However...we'd have to special-case this logic just for procs/blocks, since other converted objects would want their already-existing methods to be used.
That special-casing may not be a big deal, though. If a block passed to an interface-receiving method were re-wrapped in an additional layer that forces all calls through the block, it would be possible to implement any interface regardless of the methods it might define. And this would not really be unexpected; a literal block is not outwardly a proc "yet", and so there's no normal way a user would have actively defined methods on it expecting them to receive the interface calls.
Marking for 1.6. Time is short for the 1.6 release, but there are a couple possible courses of action:
Sorry for the confusion on this...I can appreciate that it must have been very confusing. And to be honest, I'm surprised we had not though of it before