-
Bug
-
Resolution: Unresolved
-
P3
-
25, 26
We've started seeing a new kind of failure having to do with the ResolutionErrorTable.
Stack: [0x0000000ac0a10000,0x0000000ac1413000], sp=0x0000000ac1411870, free space=10246k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.dylib+0xac50b8] SystemDictionary::resolve_or_null(Symbol*, Handle, JavaThread*)+0x24
V [libjvm.dylib+0xac5050] SystemDictionary::resolve_or_fail(Symbol*, Handle, bool, JavaThread*)+0x24
V [libjvm.dylib+0x3aaf84] Exceptions::new_exception(JavaThread*, Symbol*, Symbol*, JavaCallArguments*, Handle, Handle)+0x4c
V [libjvm.dylib+0x3aaaf0] Exceptions::new_exception(JavaThread*, Symbol*, char const*, Handle, Handle, Exceptions::ExceptionMsgToUtf8Mode)+0xcc
V [libjvm.dylib+0x3ab22c] Exceptions::_throw_msg(JavaThread*, char const*, int, Symbol*, char const*)+0x6c
V [libjvm.dylib+0x2eab70] ConstantPool::throw_resolution_error(constantPoolHandle const&, int, JavaThread*)+0xfc
V [libjvm.dylib+0x2ea7f0] ConstantPool::klass_at_impl(constantPoolHandle const&, int, JavaThread*)+0x90
V [libjvm.dylib+0x4c6550] InstanceKlass::compute_enclosing_class(bool*, JavaThread*) const+0x118
V [libjvm.dylib+0x5bba44] JVM_GetDeclaringClass+0x148
J 2928 java.lang.Class.getDeclaringClass0()Ljava/lang/Class; java.base@26 (0 bytes) @ 0x0000000116021c98 [0x0000000116021c00+0x0000000000000098]
J 3902 jvmci java.lang.Class.getEnclosingClass()Ljava/lang/Class; java.base@26 (46 bytes) @ 0x0000000115ff7e64 [0x0000000115ff7dc0+0x00000000000000a4]
It seems like we're entering resolve_or_null with a null class name as the crash happens immediately after entry when it's checking for array types:
# V [libjvm.dylib+0xac50b8] SystemDictionary::resolve_or_null(Symbol*, Handle, JavaThread*)+0x24
0x1082b82e0: stp x26, x25, [sp, #-0x50]!
0x1082b82e4: stp x24, x23, [sp, #0x10]
0x1082b82e8: stp x22, x21, [sp, #0x20]
0x1082b82ec: stp x20, x19, [sp, #0x30]
0x1082b82f0: stp x29, x30, [sp, #0x40]
0x1082b82f4: add x29, sp, #0x40
0x1082b82f8: mov x19, x2
0x1082b82fc: mov x20, x1
0x1082b8300: mov x24, x0
=> 0x1082b8304: ldrh w8, [x0, #4]
x0 is never null checked before access and I think the only way it could be null is if find_resolution_error returned null (https://github.com/openjdk/jdk/blob/a6be2286421e069a292c749eecd6bdc38a8deaf2/src/hotspot/share/oops/constantPool.cpp#L996). A quick inspection of the HotSpot code doesn't show any obvious races that could account for this. It does appear that the error symbol is null when a nest host error is recorded (https://github.com/openjdk/jdk/blob/4680dc983169d48fcf83eb50dc60e32e79d5d976/src/hotspot/share/classfile/resolutionErrors.hpp#L84) and that would certainly lead to the crash we are seeing. This is occurring in the midst of a large Java native image build but it should be possible to write a test to exercise this pattern. Certainly there's a mismatch between the how resolution errors are recorded and how they are rethrown.
This has been seen with both JDK25 and JDK26.
Stack: [0x0000000ac0a10000,0x0000000ac1413000], sp=0x0000000ac1411870, free space=10246k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.dylib+0xac50b8] SystemDictionary::resolve_or_null(Symbol*, Handle, JavaThread*)+0x24
V [libjvm.dylib+0xac5050] SystemDictionary::resolve_or_fail(Symbol*, Handle, bool, JavaThread*)+0x24
V [libjvm.dylib+0x3aaf84] Exceptions::new_exception(JavaThread*, Symbol*, Symbol*, JavaCallArguments*, Handle, Handle)+0x4c
V [libjvm.dylib+0x3aaaf0] Exceptions::new_exception(JavaThread*, Symbol*, char const*, Handle, Handle, Exceptions::ExceptionMsgToUtf8Mode)+0xcc
V [libjvm.dylib+0x3ab22c] Exceptions::_throw_msg(JavaThread*, char const*, int, Symbol*, char const*)+0x6c
V [libjvm.dylib+0x2eab70] ConstantPool::throw_resolution_error(constantPoolHandle const&, int, JavaThread*)+0xfc
V [libjvm.dylib+0x2ea7f0] ConstantPool::klass_at_impl(constantPoolHandle const&, int, JavaThread*)+0x90
V [libjvm.dylib+0x4c6550] InstanceKlass::compute_enclosing_class(bool*, JavaThread*) const+0x118
V [libjvm.dylib+0x5bba44] JVM_GetDeclaringClass+0x148
J 2928 java.lang.Class.getDeclaringClass0()Ljava/lang/Class; java.base@26 (0 bytes) @ 0x0000000116021c98 [0x0000000116021c00+0x0000000000000098]
J 3902 jvmci java.lang.Class.getEnclosingClass()Ljava/lang/Class; java.base@26 (46 bytes) @ 0x0000000115ff7e64 [0x0000000115ff7dc0+0x00000000000000a4]
It seems like we're entering resolve_or_null with a null class name as the crash happens immediately after entry when it's checking for array types:
# V [libjvm.dylib+0xac50b8] SystemDictionary::resolve_or_null(Symbol*, Handle, JavaThread*)+0x24
0x1082b82e0: stp x26, x25, [sp, #-0x50]!
0x1082b82e4: stp x24, x23, [sp, #0x10]
0x1082b82e8: stp x22, x21, [sp, #0x20]
0x1082b82ec: stp x20, x19, [sp, #0x30]
0x1082b82f0: stp x29, x30, [sp, #0x40]
0x1082b82f4: add x29, sp, #0x40
0x1082b82f8: mov x19, x2
0x1082b82fc: mov x20, x1
0x1082b8300: mov x24, x0
=> 0x1082b8304: ldrh w8, [x0, #4]
x0 is never null checked before access and I think the only way it could be null is if find_resolution_error returned null (https://github.com/openjdk/jdk/blob/a6be2286421e069a292c749eecd6bdc38a8deaf2/src/hotspot/share/oops/constantPool.cpp#L996). A quick inspection of the HotSpot code doesn't show any obvious races that could account for this. It does appear that the error symbol is null when a nest host error is recorded (https://github.com/openjdk/jdk/blob/4680dc983169d48fcf83eb50dc60e32e79d5d976/src/hotspot/share/classfile/resolutionErrors.hpp#L84) and that would certainly lead to the crash we are seeing. This is occurring in the midst of a large Java native image build but it should be possible to write a test to exercise this pattern. Certainly there's a mismatch between the how resolution errors are recorded and how they are rethrown.
This has been seen with both JDK25 and JDK26.