JDK-8022887 : Assertion hit while using class and redefining it with RedefineClasses simultaneously
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: hs25
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-08-13
  • Updated: 2015-05-26
  • Resolved: 2013-09-20
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 8 Other
8Fixed hs25Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
As far as I understand it's okay to use class and redefine it simultaneously. The following tests invoke class methods with reflection and redefine it with multiple threads meanwhile. It results in assertion in reflection.cpp. Probably reflection implementation isn't thread safe in this sense.

nsk/jvmti/RedefineClasses/StressRedefine
nsk/jvmti/RedefineClasses/StressRedefineWithoutBytecodeCorruption 

#  Internal Error (/HUDSON/workspace/2-build-linux-i586/jdk8/5336/hotspot/src/share/vm/runtime/reflection.cpp:1065), pid=12394, tid=3793415024
#  assert(java_args.size_of_parameters() == method->size_of_parameters()) failed: just checking
#
# JRE version: Java(TM) SE Runtime Environment (8.0-b102) (build 1.8.0-ea-fastdebug-b102)
# Java VM: Java HotSpot(TM) Client VM (25.0-b44-fastdebug mixed mode linux-x86 )
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0xe23a1800):  JavaThread "Thread-1" [_thread_in_vm, id=12734, stack(0xe215e000,0xe21af000)]

Stack: [0xe215e000,0xe21af000],  sp=0xe21ad5d0,  free space=317k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x894045]  VMError::report_and_die()+0x185
V  [libjvm.so+0x3388b8]  report_vm_error(char const*, int, char const*, char const*)+0x68
V  [libjvm.so+0x77d2bd]  Reflection::invoke(instanceKlassHandle, methodHandle, Handle, bool, objArrayHandle, BasicType, objArrayHandle, bool, Thread*)+0x6dd
V  [libjvm.so+0x77dff6]  Reflection::invoke_method(oopDesc*, Handle, objArrayHandle, Thread*)+0x1a6
V  [libjvm.so+0x5766e7]  JVM_InvokeMethod+0x1b7
C  [libjava.so+0xc322]  Java_sun_reflect_NativeMethodAccessorImpl_invoke0+0x32
j  sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0
j  sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
J  sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; @ 0xf43658d0 [0xf4365890+64]
j  java.lang.Thread.run()V+11
v  ~StubRoutines::call_stub
V  [libjvm.so+0x481c87]  JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)+0x17e7
V  [libjvm.so+0x709849]  os::os_exception_wrapper(void (*)(JavaValue*, methodHandle*, JavaCallArguments*, Thread*), JavaValue*, methodHandle*, JavaCallArguments*, Thread*)+0x19
V  [libjvm.so+0x48235b]  JavaCalls::call_virtual(JavaValue*, KlassHandle, Symbol*, Symbol*, JavaCallArguments*, Thread*)+0x4eb
V  [libjvm.so+0x482a11]  JavaCalls::call_virtual(JavaValue*, Handle, KlassHandle, Symbol*, Symbol*, Thread*)+0x61
V  [libjvm.so+0x542b1e]  thread_entry(JavaThread*, Thread*)+0x7e
V  [libjvm.so+0x842429]  JavaThread::thread_main_inner()+0x1b9
V  [libjvm.so+0x842738]  JavaThread::run()+0x268
V  [libjvm.so+0x711e69]  java_start(Thread*)+0x119
C  [libpthread.so.0+0x5e72]  start_thread+0xd2

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0
j  sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
J  sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; @ 0xf43658d0 [0xf4365890+64]
J  java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; @ 0xf4365454 [0xf4365380+212]
j  nsk.jvmti.RedefineClasses.StressRedefine$StaticMethodCaller.run()V+163
j  java.lang.Thread.run()V+11
v  ~StubRoutines::call_stub

Steps to reproduce: go to vmsqe-core2q-03, cd to /export/local/repr1 and run local.rerun.sh.1 until it returns nonzero as exit code. Failure is fairly reproducible. It takes ~8 attempts to reproduce.
Comments
So in this case, the methods array in InstanceKlass is not deallocated (although it can be), but one of the methods could be marked as obsolete and given an out-of-range method_idnum, so if code tries to call the new version of this method, it will get a bogus method instead. InstanceKlass::method_with_idnum() was returning the last method in the list if one with no matching idnum is found. The fix is to do a bunch of things - return NULL for method_with_idnum() not found change GetClassDeclaredMethods and GetClassDeclaredConstructors so that it can do something reasonable with redefinition while the methods array is iterated on remove methodHandle array from InstanceKlass PreviousVersionWalker because methodHandles assume that this sort of handle is stack allocated so that the destructor will be called
18-09-2013

Here's another crash I saw in a different AdHoc test run. JDK: Java(TM) SE Runtime Environment 1.8.0 b106 (1.8.0-ea-fastdebug-b106) VM: Java HotSpot(TM) 64-Bit Server VM 25.0 b49 (25.0-b49-internal-201309100245.ddaugher.8019835_exp-fastdebug) nsk/jvmti/RedefineClasses/StressRedefineWithoutBytecodeCorruption This test run failed due to the following assertion failure: # Internal Error (/opt/jprt/T/P1/024512.ddaugher/s/src/share/vm/runtime/reflection.cpp:1065), pid=16571, tid=34 # assert(java_args.size_of_parameters() == method->size_of_parameters()) failed: just checking Here is a snippet of the stack trace: Stack: [0xfffffd7f97ced000,0xfffffd7f97ded000], sp=0xfffffd7f97de9a60, free space=1010k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) V [libjvm.so+0x27aa6cc] void VMError::report(outputStream*)+0x92c V [libjvm.so+0x27abc08] void VMError::report_and_die()+0x56c V [libjvm.so+0xf66c1f] void report_vm_error(const char*,int,const char*,const char*)+0x55f V [libjvm.so+0x23a7904] oop Reflection::invoke(instanceKlassHandle,methodHandle,Handle,bool,objArrayHandle,BasicType,objArrayHandle,bool,Thread*)+0x3b30 V [libjvm.so+0x23a8a04] oop Reflection::invoke_method(oop,Handle,objArrayHandle,Thread*)+0x828 V [libjvm.so+0x1a1e68c] JVM_InvokeMethod+0x9d8 C [libjava.so+0x1325a] Java_sun_reflect_NativeMethodAccessorImpl_invoke0+0x12 j sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0 J 3549 C2 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (62 bytes) @ 0xfffffd7fecf1c458 [0xfffffd7fecf1bdc0+0x698] J 2919% C1 nsk.jvmti.RedefineClasses.StressRedefine$NonstaticMethodCaller.run()V (211 bytes) @ 0xfffffd7fecf0eb6c [0xfffffd7fecf0b840+0x332c] j java.lang.Thread.run()V+11 v ~StubRoutines::call_stub V [libjvm.so+0x161f7f7] void JavaCalls::call_helper(JavaValue*,methodHandle*,JavaCallArguments*,Thread*)+0x14b3 V [libjvm.so+0x161e303] void JavaCalls::call(JavaValue*,methodHandle,JavaCallArguments*,Thread*)+0x3f V [libjvm.so+0x161ba5e] void JavaCalls::call_virtual(JavaValue*,KlassHandle,Symbol*,Symbol*,JavaCallArguments*,Thread*)+0x65e V [libjvm.so+0x161c21a] void JavaCalls::call_virtual(JavaValue*,Handle,KlassHandle,Symbol*,Symbol*,Thread*)+0xda V [libjvm.so+0x19e0ec0] void thread_entry(JavaThread*,Thread*)+0xb0 V [libjvm.so+0x2624b15] void JavaThread::thread_main_inner()+0x521 V [libjvm.so+0x262422b] void JavaThread::run()+0x84f V [libjvm.so+0x21a16be] java_start+0x1ce C [libc.so.1+0xd704b] _thr_setup+0x5b C [libc.so.1+0xd7280] ht_pause+0x10 Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) j sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0 J 3549 C2 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (62 bytes) @ 0xfffffd7fecf1c458 [0xfffffd7fecf1bdc0+0x698] J 2919% C1 nsk.jvmti.RedefineClasses.StressRedefine$NonstaticMethodCaller.run()V (211 bytes) @ 0xfffffd7fecf0eb6c [0xfffffd7fecf0b840+0x332c] j java.lang.Thread.run()V+11 v ~StubRoutines::call_stub And here is a snippet fro the .log file: [2013-09-10T15:22:03.36] Dumping core ... [2013-09-10T15:22:34.55] # Test level exit status: 6
10-09-2013

For windows RULE nsk/jvmti/RedefineClasses/StressRedefineWithoutBytecodeCorruption Crash EXCEPTION_ACCESS_VIOLATION
09-09-2013

Yes, this is possible for this test. It gets declared classes and starts redefining them.
05-09-2013

I found the bug! JVM_GetClassDeclaredMethods gets the methods array from the InstanceKlass, safepoints and the class is redefined. The methods array cached is no longer valid. It's a naked Method* problem (only as an array).
04-09-2013

Ran memchecker - machine memory system is fine.
26-08-2013

I've reproduced this bug consistently. It looks like the java.lang.reflect.Method slot field is 376 in one case which is out of range for the number of methods in the class. Something has corrupted this field. I fixed a problem where we were getting the wrong method in InstanceKlass::method_with_idnum() if the Method can't be found, which is the case for index 376 and now I am getting the process consistently killed by the OS with no core file or hs_err file. local.rerun.sh: line 91: 560 Killed ${JAVA} ${JAVA_OPTS} ${EXECUTE_CLASS} ${TEST_ARGS} > out I think there is something wrong with this machine.
22-08-2013

There's a core file in that directory but it has no symbols if I gdb it.
15-08-2013

I don't think I did. I just saw java.lang.reflect.Method.invoke in the stack trace and thought it was something else.
15-08-2013

Coleen thinks she has already fixed this.
13-08-2013

I managed to reproduce failure with -Xcomp option on host sc11136470, scripts reside in dir /export/local/repr1. It took ~40 attempts.
13-08-2013