JRuby (please use github issues at http://bugs.jruby.org)
  1. JRuby (please use github issues at http://bugs.jruby.org)
  2. JRUBY-4756

Interface that has abstract methods final in Ruby hierarchy break "real class" implementation

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: JRuby 1.5
    • Fix Version/s: None
    • Component/s: Java Integration
    • Labels:
      None
    • Number of attachments :
      0

      Description

      This is a problem with earlier versions of jruby-rack, which has an interface org.jruby.rack.RackApplication with a getRuntime method of identical signature to our own getRuntime on IRubyObject. The implementation of that interface then provides its own getRuntime method.

      Under JRuby 1.4, where the class generated for an interface impl was off to the side of the org.jruby.RubyObject class hierarchy, this worked fine. Under JRuby 1.5, where the interface impl is actually a subclass of RubyObject, getRuntime in that hierarchy is now final and so the implementation fails to load properly.

      There are a few fixes required for this:

      • We should have a better error when an interface method is already final in the Ruby class hierarchy (or in the extending class hierarchy for Ruby-extending-Java) rather than letting the verification error to bubble out.
      • jruby-rack needs a fix; Nick Sieger has so far fixed this by dodging the interface impl logic by < java.lang.Object. this causes the impl class to not descend from RubyObject, and so getRuntime can be implemented ok. This may or may not be an ok fix; since the concrete extension logic is rather involved, it could be a performance issue. But it's not a bad fix from a functional perspective.

      Since jruby-rack has already been patched for this, there's no criticality to this issue for JRuby 1.5. However we should get a better error in place for JRuby 1.6 at the latest, and potentially also prioritize getting "real class" extension logic fully functional so that jruby-rack's current fix does not incur any (potential) perf penalty.

      Here is a session showing a trivial reproduction of the problem:

      ~/projects/jruby &#10132; cat blah.duby 
      import org.jruby.Ruby
      
      interface GetRuntime do
        def getRuntime() returns Ruby; end
      end
      
      ~/projects/jruby &#10132; ../duby/bin/dubyc blah.duby
      
      ~/projects/jruby &#10132; javap GetRuntime
      Compiled from "blah.duby"
      public interface GetRuntime{
          public abstract org.jruby.Ruby getRuntime();
      }
      
      
      ~/projects/jruby &#10132; jruby -rjava -e "class Foo; include Java::GetRuntime; def getRuntime; nil; end; end; Foo.new"
      ClassLoader.java:-2:in `defineClass1': java.lang.VerifyError: class Foo_379897791 overrides final method getRuntime.()Lorg/jruby/Ruby;
      	from ClassLoader.java:698:in `defineClass'
      	from JRubyClassLoader.java:39:in `defineClass'
      	from RealClassGenerator.java:462:in `defineRealImplClass'
      	from RealClassGenerator.java:70:in `createRealImplClass'
      	from Java.java:1169:in `generateRealClass'
      	from JavaInterfaceTemplate.java:269:in `call'
      	from DynamicMethod.java:182:in `call'
      	from DynamicMethod.java:178:in `call'
      	from CachingCallSite.java:289:in `cacheAndCall'
      	from CachingCallSite.java:108:in `call'
      	from -e:1:in `__file__'
      	from -e:-1:in `load'
      	from Ruby.java:683:in `runScript'
      	from Ruby.java:566:in `runNormally'
      	from Ruby.java:412:in `runFromMain'
      	from Main.java:286:in `run'
      	from Main.java:128:in `run'
      	from Main.java:97:in `main'
      

        Activity

        Hide
        Charles Oliver Nutter added a comment -

        Another note. I at first thought that interface impl should not define the impl method for a final superclass method if it's not actually defined in the Ruby class. However, we already need to have those impls generated since interface implementations might implement them with method_missing. Because of this, all methods from all interfaces included into a Ruby class must be generated into the subclass and must dynamically dispatch to them. That eliminates the possibility of quietly just ignoring the mismatch between an interface-specified method and a final superclass method.

        Because of this, the interface provided in jruby-rack will always error, since the resulting class will always try to reimplement getRuntime even though it's final in the superclass. We can produce a nicer error, which would at least point out the actual problem, but there's no way to fix the issue per se. You would need to extend from a different hierarchy (the current jruby-rack fix) or remove the offending method from the interface.

        Show
        Charles Oliver Nutter added a comment - Another note. I at first thought that interface impl should not define the impl method for a final superclass method if it's not actually defined in the Ruby class. However, we already need to have those impls generated since interface implementations might implement them with method_missing. Because of this, all methods from all interfaces included into a Ruby class must be generated into the subclass and must dynamically dispatch to them. That eliminates the possibility of quietly just ignoring the mismatch between an interface-specified method and a final superclass method. Because of this, the interface provided in jruby-rack will always error, since the resulting class will always try to reimplement getRuntime even though it's final in the superclass. We can produce a nicer error, which would at least point out the actual problem, but there's no way to fix the issue per se. You would need to extend from a different hierarchy (the current jruby-rack fix) or remove the offending method from the interface.

          People

          • Assignee:
            Charles Oliver Nutter
            Reporter:
            Charles Oliver Nutter
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: