From 2be1f10fec37057a4532fbbc3467b41240c4dba9 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 10 May 2023 01:48:03 +0000 Subject: [PATCH] 8307399: get rid of compatibility ThreadStart/ThreadEnd events for virtual threads Reviewed-by: alanb, pchilanomate, cjplummer --- src/hotspot/share/prims/jvmti.xml | 27 +++++++------------ src/hotspot/share/prims/jvmtiExport.cpp | 24 ++++++++++------- src/hotspot/share/prims/jvmtiThreadState.cpp | 13 +-------- src/hotspot/share/runtime/globals.hpp | 4 --- .../VirtualThreadStartTest.java | 13 +++++---- .../libVirtualThreadStartTest.cpp | 13 ++++++--- 6 files changed, 41 insertions(+), 53 deletions(-) diff --git a/src/hotspot/share/prims/jvmti.xml b/src/hotspot/share/prims/jvmti.xml index 67b49786b8e..152f72ff7a2 100644 --- a/src/hotspot/share/prims/jvmti.xml +++ b/src/hotspot/share/prims/jvmti.xml @@ -9697,6 +9697,7 @@ myInit() {
  • +
  • @@ -12249,6 +12250,8 @@ myInit() {
  • +
  • +
  • @@ -12937,16 +12940,10 @@ myInit() { A thread start event is generated by a new thread before its initial method executes.

    - This event is generated by platform threads. It is also generated by - virtual threads when the capability - - can_support_virtual_threads is not enabled. - Agents without support for virtual threads that enable this event will - therefore be notified by all newly started threads. + This event is generated by platform thread. It is not generated by virtual threads.

    - If the capability can_support_virtual_threads is enabled then - this event is not generated by virtual threads. Agents with support for - virtual threads can enable + Agents with the can_support_virtual_threads capability + can enable the event to be notified by newly started virtual threads.

    A platform thread may be listed in the array returned by @@ -12984,16 +12981,10 @@ myInit() { A thread end event is generated by a terminating thread after its initial method has finished execution.

    - This event is generated by platform threads. It is also generated by - virtual threads when the capability - - can_support_virtual_threads is not enabled. - Agents without support for virtual threads that enable this event for - all threads will therefore be notified by all terminating threads. + This event is generated by platform thread. It is not generated by virtual threads.

    - If the capability can_support_virtual_threads is enabled then - this event is not generated by virtual threads. Agents with support for - virtual threads can enable + Agents with the can_support_virtual_threads capability + can enable the event to be notified by terminating virtual threads.

    A platform thread may be listed in the array returned by diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index e4a0ccd8796..0dd00937d1b 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -1476,11 +1476,13 @@ void JvmtiExport::post_thread_start(JavaThread *thread) { // do JVMTI thread initialization (if needed) JvmtiEventController::thread_started(thread); - if (JvmtiExport::can_support_virtual_threads() && thread->threadObj()->is_a(vmClasses::BoundVirtualThread_klass())) { - // Check for VirtualThreadStart event instead. - HandleMark hm(thread); - Handle vthread(thread, thread->threadObj()); - JvmtiExport::post_vthread_start((jthread)vthread.raw_value()); + if (thread->threadObj()->is_a(vmClasses::BoundVirtualThread_klass())) { + if (JvmtiExport::can_support_virtual_threads()) { + // Check for VirtualThreadStart event instead. + HandleMark hm(thread); + Handle vthread(thread, thread->threadObj()); + JvmtiExport::post_vthread_start((jthread)vthread.raw_value()); + } return; } @@ -1520,11 +1522,13 @@ void JvmtiExport::post_thread_end(JavaThread *thread) { return; } - if (JvmtiExport::can_support_virtual_threads() && thread->threadObj()->is_a(vmClasses::BoundVirtualThread_klass())) { - // Check for VirtualThreadEnd event instead. - HandleMark hm(thread); - Handle vthread(thread, thread->threadObj()); - JvmtiExport::post_vthread_end((jthread)vthread.raw_value()); + if (thread->threadObj()->is_a(vmClasses::BoundVirtualThread_klass())) { + if (JvmtiExport::can_support_virtual_threads()) { + // Check for VirtualThreadEnd event instead. + HandleMark hm(thread); + Handle vthread(thread, thread->threadObj()); + JvmtiExport::post_vthread_end((jthread)vthread.raw_value()); + } return; } diff --git a/src/hotspot/share/prims/jvmtiThreadState.cpp b/src/hotspot/share/prims/jvmtiThreadState.cpp index 40168637d79..651b65e2f33 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.cpp +++ b/src/hotspot/share/prims/jvmtiThreadState.cpp @@ -526,17 +526,11 @@ JvmtiVTMSTransitionDisabler::VTMS_vthread_start(jobject vthread) { assert(!thread->is_in_VTMS_transition(), "sanity check"); assert(!thread->is_in_tmp_VTMS_transition(), "sanity check"); + JvmtiEventController::thread_started(thread); if (JvmtiExport::can_support_virtual_threads()) { - JvmtiEventController::thread_started(thread); if (JvmtiExport::should_post_vthread_start()) { JvmtiExport::post_vthread_start(vthread); } - } else { // compatibility for vthread unaware agents: legacy thread_start - if (PostVirtualThreadCompatibleLifecycleEvents && - JvmtiExport::should_post_thread_life()) { - // JvmtiEventController::thread_started is called here - JvmtiExport::post_thread_start(thread); - } } // post VirtualThreadMount event after VirtualThreadStart if (JvmtiExport::should_post_vthread_mount()) { @@ -559,11 +553,6 @@ JvmtiVTMSTransitionDisabler::VTMS_vthread_end(jobject vthread) { if (JvmtiExport::should_post_vthread_end()) { JvmtiExport::post_vthread_end(vthread); } - } else { // compatibility for vthread unaware agents: legacy thread_end - if (PostVirtualThreadCompatibleLifecycleEvents && - JvmtiExport::should_post_thread_life()) { - JvmtiExport::post_thread_end(thread); - } } if (thread->jvmti_thread_state() != nullptr) { JvmtiExport::cleanup_thread(thread); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 23eb62bf06d..a28f8bba62f 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -698,10 +698,6 @@ const int ObjectAlignmentInBytes = 8; "Disable the use of stack guard pages if the JVM is loaded " \ "on the primordial process thread") \ \ - product(bool, PostVirtualThreadCompatibleLifecycleEvents, true, EXPERIMENTAL, \ - "Post virtual thread ThreadStart and ThreadEnd events for " \ - "virtual thread unaware agents") \ - \ product(bool, DoJVMTIVirtualThreadTransitions, true, EXPERIMENTAL, \ "Do JVMTI virtual thread mount/unmount transitions " \ "(disabling this flag implies no JVMTI events are posted)") \ diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/VirtualThreadStartTest.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/VirtualThreadStartTest.java index 79a6187a15c..e571501eea6 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/VirtualThreadStartTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/VirtualThreadStartTest.java @@ -46,6 +46,7 @@ public class VirtualThreadStartTest { private static final String AGENT_LIB = "VirtualThreadStartTest"; private static final int THREAD_CNT = 10; + private static native boolean canSupportVirtualThreads(); private static native int getAndResetStartedThreads(); public static void main(String[] args) throws Exception { @@ -55,8 +56,6 @@ public class VirtualThreadStartTest { String arg = args.length == 2 ? args[1] : ""; VirtualMachine vm = VirtualMachine.attach(String.valueOf(ProcessHandle.current().pid())); vm.loadAgentLibrary(AGENT_LIB, arg); - } else { - System.loadLibrary(AGENT_LIB); } getAndResetStartedThreads(); @@ -64,11 +63,15 @@ public class VirtualThreadStartTest { Thread.ofVirtual().name("Tested-VT-" + i).start(() -> {}).join(); } + // No VirtualThreadStart events are expected if can_support_virtual_threads is disabled. + int expStartedThreads = canSupportVirtualThreads() ? THREAD_CNT : 0; int startedThreads = getAndResetStartedThreads(); - System.out.println("ThreadStart event count: " + startedThreads + ", expected: " + THREAD_CNT); - if (startedThreads != THREAD_CNT) { + + System.out.println("ThreadStart event count: " + startedThreads + ", expected: " + expStartedThreads); + + if (startedThreads != expStartedThreads) { throw new RuntimeException("Failed: wrong ThreadStart count: " + - startedThreads + " expected: " + THREAD_CNT); + startedThreads + " expected: " + expStartedThreads); } } } diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/libVirtualThreadStartTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/libVirtualThreadStartTest.cpp index 73b122cb457..b4eefa992ef 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/libVirtualThreadStartTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/VirtualThreadStartTest/libVirtualThreadStartTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,12 +67,18 @@ void JNICALL VirtualThreadStart(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { if (!can_support_vt_enabled) { fatal(jni, "Failed: expected ThreadStart instead of VirtualThreadStart event"); } - printf("VirtualThreadStart event: %s\n", tname); + LOG("VirtualThreadStart event: %s\n", tname); started_thread_cnt++; } deallocate(jvmti, jni, (void*)tname); } +JNIEXPORT jboolean JNICALL +Java_VirtualThreadStartTest_canSupportVirtualThreads(JNIEnv* jni, jclass clazz) { + LOG("can_support_virtual_threads: %d\n", can_support_vt_enabled); + return can_support_vt_enabled ? JNI_TRUE : JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_VirtualThreadStartTest_getAndResetStartedThreads(JNIEnv* jni, jclass clazz) { RawMonitorLocker agent_start_locker(jvmti, jni, agent_event_lock); @@ -116,8 +122,7 @@ jint agent_init(JavaVM *jvm, char *options, void *reserved) { return JNI_ERR; } } - printf("agent_init: can_support_virtual_threads capability: %d\n", - caps.can_support_virtual_threads); + LOG("agent_init: can_support_virtual_threads: %d\n", caps.can_support_virtual_threads); err = jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks)); if (err != JVMTI_ERROR_NONE) {