JDK-6976636 : JVM/TI test ex03t001 fails assertion
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: hs17,8
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2010-08-12
  • Updated: 2017-01-30
  • Resolved: 2014-03-18
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 JDK 9
8u102Fixed 9 b08Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
The following test:

    nsk/jvmti/scenarios/extension/EX03/ex03t001

fails the following assertion:

    Internal Error (src/share/vm/prims/jvmtiExport.cpp:1045)
    Error: assert(prev_state == _thread_blocked,"JavaThread should be at safepoint")

Here is the URL for the oldest failure that I found in nightly:

http://sqeweb.sfbay.sun.com/nfs/tools/gtee/results/JDK7/NIGHTLY/VM/2010-02-03/GC_Baseline-Xconc/vm/linux-i586/server/mixed/linux-i586_server_mixed_nsk.quick-jvmti.testlist/analysis.html

Here is a snippet of the stack trace from the hs_err file:

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

Current thread (0x09d41800):  VMThread [stack: 0xa9177000,0xa91f8000] [id=21415]

Stack: [0xa9177000,0xa91f8000],  sp=0xa91f6b10,  free space=1fea91f6b88k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x99cc55];;  _ZN7VMError6reportEP12outputStream+0x13f5
V  [libjvm.so+0x99cee4];;  _ZN7VMError14report_and_dieEv+0x194
V  [libjvm.so+0x443e55];;  _Z24report_assertion_failurePKciS0_+0x65
V  [libjvm.so+0x6c1e42];;  _ZN11JvmtiExport17post_class_unloadEP12klassOopDesc+0x202
V  [libjvm.so+0x49aa7e];;  _ZN10Dictionary12do_unloadingEP17BoolObjectClosure+0x12fe
V  [libjvm.so+0x910737];;  _ZN16SystemDictionary12do_unloadingEP17BoolObjectClosure+0x27
V  [libjvm.so+0x427805];;  _ZN12CMSCollector17refProcessingWorkEbb+0x405
V  [libjvm.so+0x427d4f];;  _ZN12CMSCollector24checkpointRootsFinalWorkEbbb+0x28f
V  [libjvm.so+0x4283fb];;  _ZN12CMSCollector20checkpointRootsFinalEbbb+0x10b
V  [libjvm.so+0x42874c];;  _ZN12CMSCollector16do_CMS_operationENS_11CMS_op_typeE+0x1cc
V  [libjvm.so+0x99acdf];;  _ZN19VM_CMS_Final_Remark4doitEv+0xff
V  [libjvm.so+0x9ba9e2];;  _ZN12VM_Operation8evaluateEv+0x82
V  [libjvm.so+0x9b85f2];;  _ZN8VMThread18evaluate_operationEP12VM_Operation+0xb2
V  [libjvm.so+0x9b8f90];;  _ZN8VMThread4loopEv+0x210
V  [libjvm.so+0x9b952d];;  _ZN8VMThread3runEv+0xbd
V  [libjvm.so+0x7f0f49];;  _ZL10java_startP6Thread+0xf9
C  [libpthread.so.0+0x55e2]

VM_Operation (0xa9493298): CMS_Final_Remark, mode: safepoint, requested by thread 0x09cf5400
Here is the URL for a Solaris X86 instance of this failure:

http://sqeweb.sfbay.sun.com/nfs/tools/gtee/results/JDK7/NIGHTLY/VM/2010-02-10/GC_Baseline-Xinc/vm/solaris-i586/server/mixed/solaris-i586_server_mixed_nsk.quick-jvmti.testlist/analysis.html

Here is the URL for a Linux AMD64 instance of this failure:

http://sqeweb.sfbay.sun.com/nfs/tools/gtee/results/JDK7/NIGHTLY/VM/2010-02-11/GC_Baseline-Xinc/vm/linux-amd64/server/mixed/linux-amd64_server_mixed_nsk.quick-jvmti.testlist/analysis.html

While nightly doesn't show any Solaris SPARC or Windows failures,
I don't see any reason that this failure mode should be specific
to Linux X86, Linux AMD64 or Solaris X86.
Test name and assertion for DKFL
nsk/jvmti/scenarios/extension/EX03/ex03t001

;; Using jvm: "/export/local/common/jdk/baseline/solaris-sparc/jre/lib/sparc/client/libjvm.so"
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/tmp/jprt/P1/B/080317.jc234399/source/src/share/vm/prims/jvmtiExport.cpp:994), pid=20048, tid=6
#  assert(prev_state == _thread_blocked) failed: JavaThread should be at safepoint
#
# JRE version: 7.0-b141
# Java VM: Java HotSpot(TM) Client VM (21.0-b12-internal-201105170803.jc234399.7041440_fix-fastdebug mixed mode solaris-sparc )
# Core dump written. Default location: /export/local/50462.JDK7.NIGHTLY.VM+solaris-sparc_vm_client_mixed_nsk.quick-jvmti.testlist/results/ResultDir/ex03t001/core or core.20048
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

Comments
The suggested fix is: diff -r 7380034e5b31 src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Mon Mar 03 13:58:52 2014 -0500 +++ b/src/share/vm/prims/jvmtiExport.cpp Thu Mar 13 06:21:45 2014 -0700 @@ -993,7 +993,9 @@ void JvmtiExport::post_class_unload(Klas // Before we call the JVMTI agent, we have to set the state in the // thread for which we are proxying. JavaThreadState prev_state = real_thread->thread_state(); - assert(prev_state == _thread_blocked, "JavaThread should be at safepoint"); + assert(((Thread *)real_thread)->is_ConcurrentGC_thread() || + (real_thread->is_Java_thread() && prev_state == _thread_blocked), + "should be ConcurrentGCThread or JavaThread at safepoint"); real_thread->set_thread_state(_thread_in_native); jvmtiExtensionEvent callback = env->ext_callbacks()->ClassUnload;
14-03-2014

It looks like the jthread argument is not really needed in the class unload event callback. The jthread was specified in the JVMDI as follows: Class Events (JVMDI_EVENT_CLASS_LOAD, JVMDI_EVENT_CLASS_UNLOAD, JVMDI_EVENT_CLASS_PREPARE) typedef struct { jthread thread; jclass clazz; } JVMDI_class_event_data; My guess is that the "jclass clazz" was needed for two other events: JVMDI_EVENT_CLASS_LOAD, JVMDI_EVENT_CLASS_PREPARE I'm suggesting to remove it from the arguments list. The JDWP agent does not use the class unload events. It generates synthetic events for JDI basing on the absence of the classes in the table of currently loaded classes. So that the JPDA does not depend on the EXT_EVENT_CLASS_UNLOAD debug extension. And both JDI and JDWP do not pass the jthread argument to the event handlers. The only internal dependency is the VM SQE test ex03t001. I have a doubt we have more tests like this. More detailed suggestion is: 1. Remove this thread state check from the JvmtiExport::post_class_unload(). With the removed check this event from the CMS will be posted with the jthread argument equal to NULL. 2. Fix the VM SQE test nsk/jvmti/scenarios/extension/EX03/ex03t001 to totally ignore the thread argument. Another approach to consider is to totally remove the jclass parameter from the event callback. But I do not see it yet as an important thing to do.
13-03-2014

To Dan: I think, the class unload event needs to be handled before the class has been really unloaded. (unfortunately, I did not find any details on that in the old JVMDI spec) There are two issues with the class that has been unloaded: 1. If class is not alive then the jclass argument is useless. The jclass must be a JNI local reference which is a thread local handle (see the JNIHandles::make_local()). Such references have different addresses and can not be directly used for bookkeeping purposes. At least, the ability to get the class name out of the jclass is required. 2. There is even no way to provide such a local reference for the event handler. A class object (or a handle) is needed to create a JNI local reference: - JNIHandles::make_local(Thread* thread, oop obj) - JNIHandles::make_local(JNIEnv* env, oop obj) So that now I'm puzzled with the question how to implement this correctly.
06-03-2014

I'm failure certain that EXT_EVENT_CLASS_UNLOAD is a post action event. In other words, the event is posted after the class has been unloaded. The jclass value can simply be used to update an internal mapping list in the agent. It cannot be used for normal operations that would work on a live jclass.
06-03-2014

I tried to prototype the approach suggested by Dan and discovered a couple of complications. Not very sure my conclusions are exactly right, so, please, correct me if needed. 1. First complication is that class unload even callback has a jclass argument referring the class which is about to be unloaded and GC-ed. Some mechanism is needed to ensure the class is alive up to the point of the callback invocation. It is not easy to provide this if the class unload events are handled on the ServiceThread. 2. Second complication is that the initial naked Klass* pointer can be potentially redirected (not sure if the CLDs are moved around). I do not know a good way to create a global handle object when the VM_operation is executed. It looks like a good way to provide safety in this case could be to register an oops_do(). Side note: My rough ServiceThread-based prototype behaves well in terms that the test is always passed and no crashes observed. But I'm still in doubt that it is safe as it can be just luckily passed by accessing the deleted CLD data. The internal webrev link (temporary purposes): http://javaweb.sfbay.sun.com/java/svc/ss45998/webrevs/2014/hotspot/6976636-JVMTI-unload-proto/
06-03-2014