JDK-8176828: jtools do not list VM process launched with the debugger option suspend=y

David Holmes david.holmes at oracle.com
Tue Dec 4 04:06:51 UTC 2018


Hi Gary,

Somewhere in this I got the mistaken impression that it is the VMThread 
that blocks waiting for the debugger to attach, but it is actually the 
main thread executing create_vm. That simplifies things and addresses 
the concern I had about jcmds that needed VM ops.

So IIUC the only reason we can't attach is because PerfMemory is not 
"accessible" so the patch below addresses that by making it accessible 
before the main thread would block. I've looked at the initialization 
flow and moving the set_accessible call seems reasonable to me.

Thanks,
David

On 30/11/2018 10:38 pm, Gary Adams wrote:
> Here's a smaller change. I'll run through a bunch of serviceability 
> tests to make sure
> this early accessible setting does not have any unexpected side effects..
> 
> diff --git a/src/hotspot/share/runtime/thread.cpp 
> b/src/hotspot/share/runtime/thread.cpp
> --- a/src/hotspot/share/runtime/thread.cpp
> +++ b/src/hotspot/share/runtime/thread.cpp
> @@ -3902,6 +3902,9 @@
>     // may be attached late and JVMTI must track phases of VM execution
>     JvmtiExport::enter_live_phase();
> 
> +  // Make perfmemory accessible
> +  PerfMemory::set_accessible(true);
> +
>     // Notify JVMTI agents that VM initialization is complete - nop if 
> no agents.
>     JvmtiExport::post_vm_initialized();
> 
> On 11/30/18, 5:03 AM, gary.adams at oracle.com wrote:
>> It turns out that almost all the diagnostic commands provide
>> meaningful output even though the vm thread is not totally
>> initialized.
>>
>> We could declare the perfmemory initialized a little earlier ...
>>
>> diff --git a/src/hotspot/share/runtime/thread.cpp 
>> b/src/hotspot/share/runtime/thread.cpp
>> --- a/src/hotspot/share/runtime/thread.cpp
>> +++ b/src/hotspot/share/runtime/thread.cpp
>> @@ -3902,6 +3902,9 @@
>>    // may be attached late and JVMTI must track phases of VM execution
>>    JvmtiExport::enter_live_phase();
>>
>> +  // Make perfmemory accessible
>> +  create_vm_timer.end();
>> +
>>    // Notify JVMTI agents that VM initialization is complete - nop if 
>> no agents.
>>    JvmtiExport::post_vm_initialized();
>>
>> @@ -3951,7 +3954,6 @@
>>      }
>>    }
>>
>> -  create_vm_timer.end();
>>  #ifdef ASSERT
>>    _vm_complete = true;
>>  #endif
>>
>> This would be the "jcmd -l" output when the post_vm_initialized()
>> would block on the "suspend=y" processing
>>
>> 23732 jdk.jcmd/sun.tools.jcmd.JCmd -l
>> 22526 Unknown
>>
>> ... when the debugger attaches "jdb -attach 5900"
>>
>> 23771 jdk.jdi/com.sun.tools.example.debug.tty.TTY -attach 5900
>> 23884 jdk.jcmd/sun.tools.jcmd.JCmd -l
>> 22526 Unknown
>>
>> ... when the debugger starts with the "run" command
>>
>> 23922 jdk.jcmd/sun.tools.jcmd.JCmd -l
>> 23771 jdk.jdi/com.sun.tools.example.debug.tty.TTY -attach 5900
>> 22526 my
>>
>> We could also pull out the perfmemory set accessible step
>> and set it explicitly.
>>
>> ...
>>
>> On 11/28/18 11:10 PM, David Holmes wrote:
>>> I've been lurking on this ...
>>>
>>> On 29/11/2018 9:41 am, gary.adams at oracle.com wrote:
>>>> On 11/28/18 4:12 PM, Chris Plummer wrote:
>>>>> On 11/28/18 11:52 AM, Gary Adams wrote:
>>>>>> https://bugs.openjdk.java.net/browse/JDK-8156537
>>>>>>   - Added a fix for module naming
>>>>>>
>>>>>> https://bugs.openjdk.java.net/browse/JDK-8176533
>>>>>>   - Fixed a regression from JDK-816537 that prevented "jcmd <pid> 
>>>>>> <cmd>"
>>>>>>      from sending <cmd> to <pid>
>>>>>>
>>>>>> https://bugs.openjdk.java.net/browse/JDK-8176828
>>>>>>   - Requests that "jcmd -l" should list the <pid>
>>>>>>      for the VM that has not completed initialization.
>>>>>>      This is not a regression, because jdk8 jcmd did
>>>>>>      not display the uninitialized VM either.
>>>>>>
>>>>>> It appears you can send "jcmd <pid> <cmd>" to
>>>>>> the process that has not completed vm initialization.
>>>>> So what happens when you do this?
>>>> The commands work, albeit the vm thread is blocked waiting for the
>>>> debugger connection.
>>>
>>> Define "work". If the VM is partially initialized there is very 
>>> little that can be examined. If the VMThread is blocked on the 
>>> debugger connection then you can't do anything that requires a VM 
>>> operation (which includes safepoints - though at this stage if there 
>>> are no JavaThreads we're safe anyway).
>>>
>>> Thanks,
>>> David
>>>
>>>>>
>>>>> Chris
>>>>>>
>>>>>> On 11/28/18, 2:29 PM, Chris Plummer wrote:
>>>>>>> Sorry, meant to say "before JDK-8176533".
>>>>>>>
>>>>>>> Chris
>>>>>>>
>>>>>>> On 11/28/18 10:11 AM, Chris Plummer wrote:
>>>>>>>> Hi Gary,
>>>>>>>>
>>>>>>>> This seems reasonable. I just want clarification on one thing 
>>>>>>>> first. Before JDK-8176828, it listed the suspend=y process, but 
>>>>>>>> could you do anything with it? I'm assuming no, and therefore it 
>>>>>>>> makes sense not to list it at all.
>>>>>>>>
>>>>>>>> thanks,
>>>>>>>>
>>>>>>>> Chris
>>>>>>>>
>>>>>>>> On 11/28/18 8:33 AM, Gary Adams wrote:
>>>>>>>>> I'd like to close JDK-8176828 as will not fix.
>>>>>>>>>   https://bugs.openjdk.java.net/browse/JDK-8176828
>>>>>>>>>
>>>>>>>>> This bug was originally thought to be associated with
>>>>>>>>> a regression fix in JDK-8176533, but I believe there
>>>>>>>>> is simply a misunderstanding of how the "suspend=y"
>>>>>>>>> behavior is supported for the jdwp agent library.
>>>>>>>>>
>>>>>>>>> The "suspend=y" setting is designed to maximize the number
>>>>>>>>> of events that can been seen by an attaching debugger.
>>>>>>>>> This calls for the process to be waiting for the debugger 
>>>>>>>>> connection
>>>>>>>>> before the VM has been completely initialized.
>>>>>>>>>
>>>>>>>>> In particular, the thread.cpp create_vm() function causes the
>>>>>>>>> debugInit.c initialize() function to start the transport 
>>>>>>>>> connection
>>>>>>>>> and wait for an external debugger to attach. Once the dt_socket 
>>>>>>>>> connection
>>>>>>>>> is established the create_vm() function will complete. It is the
>>>>>>>>> processing of the create_vm_timer.end() that results in the
>>>>>>>>> management.cpp record_vm_startup_time() and the
>>>>>>>>> PerfMemory::set_accessible(true) to be set.
>>>>>>>>>
>>>>>>>>> Without the accessible field being set an external program can 
>>>>>>>>> not use
>>>>>>>>> the PerfMemory. That is why "jcmd -l" passes over processes which
>>>>>>>>> do not have an initialized VM running.
>>>>>>>>>
>>>>>>>>> =====
>>>>>>>>> src/hotspot/share/runtime/:
>>>>>>>>> src/jdk.jdwp.agent/share/native/libjdwp/:
>>>>>>>>>
>>>>>>>>>   thread.cpp:3587:jint Threads::create_vm(JavaVMInitArgs* args, 
>>>>>>>>> bool* canTryAgain) {
>>>>>>>>>   ...
>>>>>>>>>   thread.cpp:3610:  create_vm_timer.start();
>>>>>>>>>   ...
>>>>>>>>>   thread.cpp:3907: JvmtiExport::post_vm_initialized();
>>>>>>>>>   ...
>>>>>>>>>     debugInit.c:432:cbEarlyVMInit(jvmtiEnv *jvmti_env, JNIEnv 
>>>>>>>>> *env, jthread thread)
>>>>>>>>>     ...
>>>>>>>>>     debugInit.c:103:static void initialize(JNIEnv *env, jthread 
>>>>>>>>> thread, EventIndex triggering_ei);
>>>>>>>>>     ...
>>>>>>>>>     debugInit.c:732: (void)bagEnumerateOver(transports, 
>>>>>>>>> startTransport, &arg);
>>>>>>>>>     ...
>>>>>>>>>     debugInit.c:751:    transport_waitForConnection();
>>>>>>>>>   ...
>>>>>>>>>   thread.cpp:3955:  create_vm_timer.end();
>>>>>>>>>
>>>>>>>>> ====
>>>>>>>>> src/hotspot/share/services/management.cpp:
>>>>>>>>>
>>>>>>>>>    203  void Management::record_vm_startup_time(jlong begin, 
>>>>>>>>> jlong duration) {
>>>>>>>>>    204    // if the performance counter is not initialized,
>>>>>>>>>    205    // then vm initialization failed; simply return.
>>>>>>>>>    206    if (_begin_vm_creation_time == NULL) return;
>>>>>>>>>    207
>>>>>>>>>    208 _begin_vm_creation_time->set_value(begin);
>>>>>>>>>    209    _end_vm_creation_time->set_value(begin + duration);
>>>>>>>>>    210    PerfMemory::set_accessible(true);
>>>>>>>>>    211  }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>
> 


More information about the serviceability-dev mailing list