Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8313913

LinkageError accessing already-loaded class using invokedynamic

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • None
    • 8
    • core-libs

      I'm seeing a situation with JRuby and our JRuby/Maven integration stack where an invokedynamic-based lookup of a field handle blows up with a LinkageError on Java 8, but not on Java 11+.

      The field is JRuby's org.jruby.runtime.ThreadContext.runtime, which is of type org.jruby.Ruby, our top-level "runtime" object. The Bootstrap class tries to acquire a field accessor handle for this runtime field, resulting in a chain of exceptions that prevents the Bootstrap class from initializing. This cascades through several attempts to use indy, and in my example case eventually results in a NoClassDefFound: Bootstrap.

      The set of traces had to be captured from within a debug session at the point where ExceptionInInitializerError was first created.
      ExceptionInInitializer:
      0 = {StackTraceElement@18118} "org.jruby.ir.targets.indy.IndyValueCompiler.pushNil(IndyValueCompiler.java:133)"
      1 = {StackTraceElement@18119} "org.jruby.ir.targets.simple.NormalLocalVariableCompiler.getHeapLocalOrNil(NormalLocalVariableCompiler.java:42)"
      2 = {StackTraceElement@18120} "org.jruby.ir.targets.JVMVisitor.LocalVariable(JVMVisitor.java:2751)"
      3 = {StackTraceElement@18121} "org.jruby.ir.targets.JVMVisitor.ClosureLocalVariable(JVMVisitor.java:2656)"
      4 = {StackTraceElement@18122} "org.jruby.ir.operands.ClosureLocalVariable.visit(ClosureLocalVariable.java:49)"
      5 = {StackTraceElement@18123} "org.jruby.ir.targets.JVMVisitor.visit(JVMVisitor.java:636)"
      6 = {StackTraceElement@18124} "org.jruby.ir.targets.JVMVisitor.compileCallCommon(JVMVisitor.java:1235)"
      7 = {StackTraceElement@18125} "org.jruby.ir.targets.JVMVisitor.CallInstr(JVMVisitor.java:1225)"
      8 = {StackTraceElement@18126} "org.jruby.ir.instructions.CallInstr.visit(CallInstr.java:150)"
      9 = {StackTraceElement@18127} "org.jruby.ir.targets.JVMVisitor.visit(JVMVisitor.java:632)"
      10 = {StackTraceElement@18128} "org.jruby.ir.targets.JVMVisitor.emitScope(JVMVisitor.java:305)"

      thrown:
      com.headius.invokebinder.InvalidTransformException: java.lang.IllegalAccessException: no such field: org.jruby.runtime.ThreadContext.runtime/org.jruby.Ruby/getField
      0 = {StackTraceElement@17985} "com.headius.invokebinder.Binder.getFieldQuiet(Binder.java:1757)"
      1 = {StackTraceElement@17986} "org.jruby.ir.targets.indy.Bootstrap.<clinit>(Bootstrap.java:625)"
      2 = {StackTraceElement@17987} "org.jruby.ir.targets.indy.IndyValueCompiler.pushNil(IndyValueCompiler.java:133)"
      3 = {StackTraceElement@17988} "org.jruby.ir.targets.simple.NormalLocalVariableCompiler.getHeapLocalOrNil(NormalLocalVariableCompiler.java:42)"
      4 = {StackTraceElement@17989} "org.jruby.ir.targets.JVMVisitor.LocalVariable(JVMVisitor.java:2751)"
      5 = {StackTraceElement@17990} "org.jruby.ir.targets.JVMVisitor.ClosureLocalVariable(JVMVisitor.java:2656)"
      6 = {StackTraceElement@17991} "org.jruby.ir.operands.ClosureLocalVariable.visit(ClosureLocalVariable.java:49)"

      cause:
      java.lang.IllegalAccessException: no such field: org.jruby.runtime.ThreadContext.runtime/org.jruby.Ruby/getField
      0 = {StackTraceElement@18253} "java.lang.invoke.MemberName.makeAccessException(MemberName.java:867)"
      1 = {StackTraceElement@18254} "java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1003)"
      2 = {StackTraceElement@18255} "java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1377)"
      3 = {StackTraceElement@18256} "java.lang.invoke.MethodHandles$Lookup.findGetter(MethodHandles.java:1026)"
      4 = {StackTraceElement@18257} "com.headius.invokebinder.Binder.getField(Binder.java:1714)"
      5 = {StackTraceElement@18258} "com.headius.invokebinder.Binder.getFieldQuiet(Binder.java:1755)"
      6 = {StackTraceElement@18259} "org.jruby.ir.targets.indy.Bootstrap.<clinit>(Bootstrap.java:625)"
      7 = {StackTraceElement@18260} "org.jruby.ir.targets.indy.IndyValueCompiler.pushNil(IndyValueCompiler.java:133)"
      8 = {StackTraceElement@18261} "org.jruby.ir.targets.simple.NormalLocalVariableCompiler.getHeapLocalOrNil(NormalLocalVariableCompiler.java:42)"

      cause:
      java.lang.LinkageError: loader constraint violation: when resolving field "runtime" the class loader (instance of <bootloader>) of the referring class, org/jruby/runtime/ThreadContext, and the class loader (instance of org/codehaus/plexus/classworlds/realm/ClassRealm) for the field's resolved type, org/jruby/Ruby, have different Class objects for that type
      0 = {StackTraceElement@18393} "java.lang.invoke.MethodHandleNatives.resolve(Native Method)"
      1 = {StackTraceElement@18394} "java.lang.invoke.MemberName$Factory.resolve(MemberName.java:975)"
      2 = {StackTraceElement@18395} "java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1000)"
      3 = {StackTraceElement@18396} "java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1377)"
      4 = {StackTraceElement@18397} "java.lang.invoke.MethodHandles$Lookup.findGetter(MethodHandles.java:1026)"
      5 = {StackTraceElement@18398} "com.headius.invokebinder.Binder.getField(Binder.java:1714)"
      6 = {StackTraceElement@18399} "com.headius.invokebinder.Binder.getFieldQuiet(Binder.java:1755)"
      7 = {StackTraceElement@18400} "org.jruby.ir.targets.indy.Bootstrap.<clinit>(Bootstrap.java:625)"
      8 = {StackTraceElement@18401} "org.jruby.ir.targets.indy.IndyValueCompiler.pushNil(IndyValueCompiler.java:133)"
      9 = {StackTraceElement@18402} "org.jruby.ir.targets.simple.NormalLocalVariableCompiler.getHeapLocalOrNil(NormalLocalVariableCompiler.java:42)"

      The code that appears to fail is here:

      https://github.com/jruby/jruby/blob/3caa46bf95dd16a1725c7631efd4767551044732/core/src/main/java/org/jruby/ir/targets/indy/Bootstrap.java#L622-L625

      At the point this code loads, the org.jruby.Ruby class would have to have been loaded and active for a long time. There's no reason it should find a different class at this point.

      This may be a duplicate, because I think I ran into and reported this against an earlier JDK.

      To reproduce, you'll need to build the new_mavengem branch of JRuby here:

      https://github.com/jruby/jruby/pull/7872

      And pre-fetch the polyglot-maven snapshot build using this command from a non-project directory:

      mvn -B dependency:get -Dartifact=io.takari.polyglot:polyglot-ruby:0.4.11-SNAPSHOT -DremoteRepositories=central::default::https://repo.maven.apache.org/maven2,snapshots::::https://oss.sonatype.org/content/repositories/snapshots

      And then run JRuby's main build with the following command line on Java 8:

      MAVEN_OPTS="-Djruby.jit.threshold=0" mvn clean package

      In the past, a similar error I discussed with some of the Oracle JVM team turned out to be an incorrect handling of unresolved class references in method signatures accessed through indy. I'll try to link that issue if I can find it.

            rpallath Rajendrakumar Pallath
            headius Charles Nutter
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: