JDK-8243492 : SIGSEGV when getting class data via condy from a virtual method
  • Type: Bug
  • Component: core-libs
  • Affected Version: 15
  • Priority: P2
  • Status: Resolved
  • Resolution: Not an Issue
  • Submitted: 2020-04-23
  • Updated: 2020-05-28
  • Resolved: 2020-05-28
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 15
15Resolved
Related Reports
Blocks :  
Blocks :  
Relates :  
Description
If MethodHandles::classData is invoked from <clinit> and store them in static final fields, that works properly.

But if  MethodHandles::classData is called from a virtual method, VM crashes with SIGSEGV. 

#  SIGSEGV (0xb) at pc=0x000000010cfc5ea5, pid=10577, tid=26371
#
# JRE version: Java(TM) SE Runtime Environment (15.0) (fastdebug build 15-internal+0-adhoc.mlchung.open)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 15-internal+0-adhoc.mlchung.open, mixed mode, sharing, tiered, compressed oops, g1 gc, bsd-amd64)
# Problematic frame:
# V  [libjvm.dylib+0x7c5ea5]  CallInfo::set_common(Klass*, methodHandle const&, methodHandle const&, CallInfo::CallKind, int, Thread*)+0x55
---------------  T H R E A D  ---------------

Current thread (0x00007fade70f2a20):  JavaThread "MainThread" [_thread_in_vm, id=26371, stack(0x0000700010c13000,0x0000700010d13000)]

Stack: [0x0000700010c13000,0x0000700010d13000],  sp=0x0000700010d104c0,  free space=1013k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.dylib+0x7c5ea5]  CallInfo::set_common(Klass*, methodHandle const&, methodHandle const&, CallInfo::CallKind, int, Thread*)+0x55
V  [libjvm.dylib+0x7c60b1]  CallInfo::set_virtual(Klass*, methodHandle const&, methodHandle const&, int, Thread*)+0xb7
V  [libjvm.dylib+0x7cab28]  LinkResolver::runtime_resolve_virtual_method(CallInfo&, methodHandle const&, Klass*, Handle, Klass*, bool, Thread*)
+0x2a0
V  [libjvm.dylib+0x7ca607]  LinkResolver::resolve_virtual_call(CallInfo&, Handle, Klass*, LinkInfo const&, bool, Thread*)+0x67
V  [libjvm.dylib+0x7cbd23]  LinkResolver::resolve_invokevirtual(CallInfo&, Handle, constantPoolHandle const&, int, Thread*)+0x10d
V  [libjvm.dylib+0x5214aa]  InterpreterRuntime::resolve_invoke(JavaThread*, Bytecodes::Code)+0x48a
V  [libjvm.dylib+0x521c17]  InterpreterRuntime::resolve_from_cache(JavaThread*, Bytecodes::Code)+0x89
j  java.lang.invoke.MemoryAccessVarHandleIntHelper1+0x0000000800bf0840.accessModeTypeUncached(Ljava/lang/invoke/VarHandle$AccessMode;)Ljava/lang/invoke/MethodType;+9 java.base@15-internal
j  java.lang.invoke.VarHandle.accessModeType(Ljava/lang/invoke/VarHandle$AccessMode;)Ljava/lang/invoke/MethodType;+35 java.base@15-internal
j  java.lang.invoke.VarHandle.coordinateTypes()Ljava/util/List;+4 java.base@15-internal
j  java.lang.invoke.VarHandles.filterCoordinates(Ljava/lang/invoke/VarHandle;I[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/VarHandle;+11 java.base@15-internal
j  java.lang.invoke.MethodHandleImpl$1.filterCoordinates(Ljava/lang/invoke/VarHandle;I[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/VarHandle;+3 java.base@15-internal
j  jdk.incubator.foreign.MemoryHandles.filterCoordinates(Ljava/lang/invoke/VarHandle;I[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/VarHandle;+6 jdk.incubator.foreign@15-internal
j  jdk.internal.foreign.Utils.fixUpVarHandle(Ljava/lang/invoke/VarHandle;)Ljava/lang/invoke/VarHandle;+12 jdk.incubator.foreign@15-internal
j  jdk.internal.foreign.LayoutPath.dereferenceHandle(Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;+144 jdk.incubator.foreign@15-internal
j  jdk.incubator.foreign.MemoryLayout.lambda$varHandle$2(Ljava/lang/Class;Ljdk/internal/foreign/LayoutPath;)Ljava/lang/invoke/VarHandle;+2 jdk.incubator.foreign@15-internal
j  jdk.incubator.foreign.MemoryLayout$$Lambda$46+0x0000000800baa5a0.apply(Ljava/lang/Object;)Ljava/lang/Object;+8 jdk.incubator.foreign@15-internal
j  jdk.incubator.foreign.MemoryLayout.computePathOp(Ljdk/internal/foreign/LayoutPath;Ljava/util/function/Function;Ljava/util/Set;[Ljdk/incubator/foreign/MemoryLayout$PathElement;)Ljava/lang/Object;+89 jdk.incubator.foreign@15-internal
j  jdk.incubator.foreign.MemoryLayout.varHandle(Ljava/lang/Class;[Ljdk/incubator/foreign/MemoryLayout$PathElement;)Ljava/lang/invoke/VarHandle;+19 jdk.incubator.foreign@15-internal
j  TestByteBuffer.<clinit>()V+206


To reproduce, apply this patch to jdk/jdk repo:

diff --git a/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java b/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java
--- a/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java
+++ b/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java
@@ -287,7 +287,7 @@
         mv.visitFieldInsn(GETFIELD, Type.getInternalName(VarHandle.AccessMode.class), "at", VarHandle.AccessType.class.descriptorString());
         mv.visitLdcInsn(Type.getType(MemoryAddressProxy.class));
         mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Class.class));
-        mv.visitFieldInsn(GETSTATIC, implClassName, "carrier", Class.class.descriptorString());
+        mv.visitMethodInsn(INVOKEVIRTUAL, implClassName, "carrier", "()Ljava/lang/Class;", false);
         mv.visitFieldInsn(GETSTATIC, implClassName, "intermediate", Class[].class.descriptorString());
 
         mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(VarHandle.AccessType.class),
@@ -403,7 +403,14 @@
     void addCarrierAccessor(ClassWriter cw) {
         MethodVisitor mv = cw.visitMethod(ACC_FINAL, "carrier", "()Ljava/lang/Class;", null, null);
         mv.visitCode();
-        mv.visitFieldInsn(GETSTATIC, implClassName, "carrier", Class.class.descriptorString());
+        MethodType mtype = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class);
+        Handle bsm = new Handle(H_INVOKESTATIC, Type.getInternalName(MethodHandles.class), "classData",
+                                        mtype.descriptorString(), false);
+        ConstantDynamic dynamic = new ConstantDynamic("classData", Object[].class.descriptorString(), bsm);
+        mv.visitLdcInsn(dynamic);
+        mv.visitInsn(ICONST_0);
+        mv.visitInsn(AALOAD);
+        mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Class.class));
         mv.visitInsn(ARETURN);
         mv.visitMaxs(0, 0);
         mv.visitEnd();

VM crashses when running test/jdk/java/foreign/TestByteBuffer.java.
Comments
Thanks Lois. It turns out that this is a bug in the generated bytecode that causes the VM crash. -Xverify:all is our friend.
28-05-2020

I suspect there is an issue with the way the newly added ASM invokevirtual call is set up in MemoryAccessVarHandleGenerator::addAccessModeTypeMethod(). In CallInfo::set_virtual() the selected_method is garbage which results in a SIGSEGV in CallInfo::set_common(). But if you run the test with -Xverify:all the generated bytecodes look bad: runner starting test: java/foreign/TestByteBuffer.java runner finished test: java/foreign/TestByteBuffer.java Failed. Execution failed: `main' threw exception: org.testng.TestNGException: An error occurred while instantiating class TestByteBuffer: java.lang.VerifyError: Bad type on operand stack Exception Details: Location: java/lang/invoke/MemoryAccessVarHandleIntHelper1+0x0000000800bf0840.accessModeTypeUncached(Ljava/lang/invoke/VarHandle$AccessMode;)Ljava/lang/invoke/MethodType; @9: invokevirtual Reason: Type 'java/lang/Class' (current frame, stack[1]) is not assignable to 'java/lang/invoke/MemoryAccessVarHandleIntHelper1+0x0000000800bf0840' Current Frame: bci: @9 flags: { } locals: { 'java/lang/invoke/MemoryAccessVarHandleIntHelper1+0x0000000800bf0840', 'java/lang/invoke/VarHandle$AccessMode' } stack: { 'java/lang/invoke/VarHandle$AccessType', 'java/lang/Class' } Bytecode: 0000000: 2bb4 0039 123b c000 1cb6 003e b200 21b6 0000010: 0044 b0 Test results: failed: 1
27-05-2020

Another VM crash - SIGBUS with this patch: http://cr.openjdk.java.net/~mchung/jdk15/webrevs/8230501/webrev.00/
05-05-2020

Thank you Mandy.
04-05-2020

yes, this issue is in jdk/jdk.
04-05-2020

[~mchung] Mandy, could you please clarify: does this issue exist in jdk/jdk, and your change "prototype the fix for JDK-8239578" brought this issue to light? Or, does this issue exist only in your branch/sandbox, and not in jdk/jdk ?
04-05-2020

This issue is uncovered when I prototype the fix for JDK-8239578. This needs to be evaluated properly to explain why VM crashes. [~mseledtsov] this is not a dup of JDK-8239578.
02-05-2020

This issue is tightly coupled with JDK-8239578. Please integrate the fix for this issue together with JDK-8239578.
28-04-2020

ILW = HLM = P3
28-04-2020