-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
8
-
aarch64
-
os_x
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.
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.