8287496: Alternative virtual thread implementation that maps to OS thread
Reviewed-by: rehn, mchung
This commit is contained in:
parent
199832a710
commit
6ff2d89ea1
@ -155,6 +155,7 @@ JVM_IsFinalizationEnabled
|
|||||||
JVM_IsHiddenClass
|
JVM_IsHiddenClass
|
||||||
JVM_IsInterface
|
JVM_IsInterface
|
||||||
JVM_IsPreviewEnabled
|
JVM_IsPreviewEnabled
|
||||||
|
JVM_IsContinuationsSupported
|
||||||
JVM_IsPrimitiveClass
|
JVM_IsPrimitiveClass
|
||||||
JVM_IsRecord
|
JVM_IsRecord
|
||||||
JVM_IsSameClassPackage
|
JVM_IsSameClassPackage
|
||||||
|
@ -53,6 +53,8 @@ define_pd_global(intx, OptoLoopAlignment, 16);
|
|||||||
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
|
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
|
||||||
#define MIN_STACK_RESERVED_PAGES (0)
|
#define MIN_STACK_RESERVED_PAGES (0)
|
||||||
|
|
||||||
|
define_pd_global(bool, VMContinuations, true);
|
||||||
|
|
||||||
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
|
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
|
||||||
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
||||||
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
||||||
|
@ -53,6 +53,8 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
|||||||
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
||||||
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
||||||
|
|
||||||
|
define_pd_global(bool, VMContinuations, false);
|
||||||
|
|
||||||
#if defined(COMPILER1) || defined(COMPILER2)
|
#if defined(COMPILER1) || defined(COMPILER2)
|
||||||
define_pd_global(intx, InlineSmallCode, 1500);
|
define_pd_global(intx, InlineSmallCode, 1500);
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,6 +54,8 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
|||||||
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
||||||
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
||||||
|
|
||||||
|
define_pd_global(bool, VMContinuations, false);
|
||||||
|
|
||||||
// Use large code-entry alignment.
|
// Use large code-entry alignment.
|
||||||
define_pd_global(uintx, CodeCacheSegmentSize, 128);
|
define_pd_global(uintx, CodeCacheSegmentSize, 128);
|
||||||
define_pd_global(intx, CodeEntryAlignment, 128);
|
define_pd_global(intx, CodeEntryAlignment, 128);
|
||||||
|
@ -58,6 +58,8 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
|||||||
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
||||||
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
||||||
|
|
||||||
|
define_pd_global(bool, VMContinuations, false);
|
||||||
|
|
||||||
define_pd_global(bool, RewriteBytecodes, true);
|
define_pd_global(bool, RewriteBytecodes, true);
|
||||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
|||||||
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
||||||
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
||||||
|
|
||||||
|
define_pd_global(bool, VMContinuations, false);
|
||||||
|
|
||||||
define_pd_global(bool, RewriteBytecodes, true);
|
define_pd_global(bool, RewriteBytecodes, true);
|
||||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||||
|
|
||||||
|
@ -77,6 +77,12 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
|||||||
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
||||||
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
define_pd_global(bool, VMContinuations, true);
|
||||||
|
#else
|
||||||
|
define_pd_global(bool, VMContinuations, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
define_pd_global(bool, RewriteBytecodes, true);
|
define_pd_global(bool, RewriteBytecodes, true);
|
||||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
|||||||
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
|
||||||
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
|
||||||
|
|
||||||
|
define_pd_global(bool, VMContinuations, false);
|
||||||
|
|
||||||
define_pd_global(bool, RewriteBytecodes, true);
|
define_pd_global(bool, RewriteBytecodes, true);
|
||||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@
|
|||||||
do_klass(Thread_FieldHolder_klass, java_lang_Thread_FieldHolder ) \
|
do_klass(Thread_FieldHolder_klass, java_lang_Thread_FieldHolder ) \
|
||||||
do_klass(Thread_Constants_klass, java_lang_Thread_Constants ) \
|
do_klass(Thread_Constants_klass, java_lang_Thread_Constants ) \
|
||||||
do_klass(ThreadGroup_klass, java_lang_ThreadGroup ) \
|
do_klass(ThreadGroup_klass, java_lang_ThreadGroup ) \
|
||||||
|
do_klass(BasicVirtualThread_klass, java_lang_BaseVirtualThread ) \
|
||||||
do_klass(VirtualThread_klass, java_lang_VirtualThread ) \
|
do_klass(VirtualThread_klass, java_lang_VirtualThread ) \
|
||||||
do_klass(Properties_klass, java_util_Properties ) \
|
do_klass(Properties_klass, java_util_Properties ) \
|
||||||
do_klass(Module_klass, java_lang_Module ) \
|
do_klass(Module_klass, java_lang_Module ) \
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
template(java_lang_Thread_FieldHolder, "java/lang/Thread$FieldHolder") \
|
template(java_lang_Thread_FieldHolder, "java/lang/Thread$FieldHolder") \
|
||||||
template(java_lang_Thread_Constants, "java/lang/Thread$Constants") \
|
template(java_lang_Thread_Constants, "java/lang/Thread$Constants") \
|
||||||
template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \
|
template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \
|
||||||
|
template(java_lang_BaseVirtualThread, "java/lang/BaseVirtualThread") \
|
||||||
template(java_lang_VirtualThread, "java/lang/VirtualThread") \
|
template(java_lang_VirtualThread, "java/lang/VirtualThread") \
|
||||||
template(java_lang_Cloneable, "java/lang/Cloneable") \
|
template(java_lang_Cloneable, "java/lang/Cloneable") \
|
||||||
template(java_lang_Throwable, "java/lang/Throwable") \
|
template(java_lang_Throwable, "java/lang/Throwable") \
|
||||||
|
@ -169,7 +169,10 @@ JNIEXPORT jobjectArray JNICALL
|
|||||||
JVM_GetVmArguments(JNIEnv *env);
|
JVM_GetVmArguments(JNIEnv *env);
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
JVM_IsPreviewEnabled(JNIEnv* env);
|
JVM_IsPreviewEnabled(void);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
JVM_IsContinuationsSupported(void);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_InitializeFromArchive(JNIEnv* env, jclass cls);
|
JVM_InitializeFromArchive(JNIEnv* env, jclass cls);
|
||||||
|
@ -151,7 +151,11 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan
|
|||||||
case vmIntrinsics::_dsqrt: return java_lang_math_sqrt;
|
case vmIntrinsics::_dsqrt: return java_lang_math_sqrt;
|
||||||
case vmIntrinsics::_dsqrt_strict: return native;
|
case vmIntrinsics::_dsqrt_strict: return native;
|
||||||
case vmIntrinsics::_Reference_get: return java_lang_ref_reference_get;
|
case vmIntrinsics::_Reference_get: return java_lang_ref_reference_get;
|
||||||
case vmIntrinsics::_Continuation_doYield: return java_lang_continuation_doYield;
|
case vmIntrinsics::_Continuation_doYield:
|
||||||
|
if (VMContinuations) {
|
||||||
|
return java_lang_continuation_doYield;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case vmIntrinsics::_Object_init:
|
case vmIntrinsics::_Object_init:
|
||||||
if (RegisterFinalizersAtInit && m->code_size() == 1) {
|
if (RegisterFinalizersAtInit && m->code_size() == 1) {
|
||||||
// We need to execute the special return bytecode to check for
|
// We need to execute the special return bytecode to check for
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
#include "prims/jvm_misc.hpp"
|
#include "prims/jvm_misc.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "prims/jvmtiThreadState.hpp"
|
#include "prims/jvmtiThreadState.hpp"
|
||||||
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
#include "runtime/fieldDescriptor.inline.hpp"
|
#include "runtime/fieldDescriptor.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
@ -3143,7 +3144,11 @@ JNI_END
|
|||||||
|
|
||||||
JNI_ENTRY(jboolean, jni_IsVirtualThread(JNIEnv* env, jobject obj))
|
JNI_ENTRY(jboolean, jni_IsVirtualThread(JNIEnv* env, jobject obj))
|
||||||
oop thread_obj = JNIHandles::resolve_external_guard(obj);
|
oop thread_obj = JNIHandles::resolve_external_guard(obj);
|
||||||
return java_lang_VirtualThread::is_instance(thread_obj) ? JNI_TRUE : JNI_FALSE;
|
if (thread_obj != NULL && thread_obj->is_a(vmClasses::BasicVirtualThread_klass())) {
|
||||||
|
return JNI_TRUE;
|
||||||
|
} else {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
|
|
||||||
@ -3987,6 +3992,13 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No JVM TI with --enable-preview and no continuations support.
|
||||||
|
if (!VMContinuations && Arguments::enable_preview() && JvmtiExport::is_jvmti_version(version)) {
|
||||||
|
*penv = NULL;
|
||||||
|
ret = JNI_EVERSION;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) {
|
if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3487,10 +3487,13 @@ JVM_LEAF(jboolean, JVM_IsSupportedJNIVersion(jint version))
|
|||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jboolean, JVM_IsPreviewEnabled(JNIEnv *env))
|
JVM_LEAF(jboolean, JVM_IsPreviewEnabled(void))
|
||||||
return Arguments::enable_preview() ? JNI_TRUE : JNI_FALSE;
|
return Arguments::enable_preview() ? JNI_TRUE : JNI_FALSE;
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
JVM_LEAF(jboolean, JVM_IsContinuationsSupported(void))
|
||||||
|
return VMContinuations ? JNI_TRUE : JNI_FALSE;
|
||||||
|
JVM_END
|
||||||
|
|
||||||
// String support ///////////////////////////////////////////////////////////////////////////
|
// String support ///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -412,11 +412,7 @@ void Continuations::init() {
|
|||||||
// While virtual threads are in Preview, there are some VM mechanisms we disable if continuations aren't used
|
// While virtual threads are in Preview, there are some VM mechanisms we disable if continuations aren't used
|
||||||
// See NMethodSweeper::do_stack_scanning and nmethod::is_not_on_continuation_stack
|
// See NMethodSweeper::do_stack_scanning and nmethod::is_not_on_continuation_stack
|
||||||
bool Continuations::enabled() {
|
bool Continuations::enabled() {
|
||||||
#if defined(AMD64) || defined(AARCH64)
|
return VMContinuations && Arguments::enable_preview();
|
||||||
return Arguments::enable_preview();
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We initialize the _gc_epoch to 2, because previous_completed_gc_marking_cycle
|
// We initialize the _gc_epoch to 2, because previous_completed_gc_marking_cycle
|
||||||
|
@ -2000,6 +2000,9 @@ const intx ObjectAlignmentInBytes = 8;
|
|||||||
"Path to the directory where a temporary file will be created " \
|
"Path to the directory where a temporary file will be created " \
|
||||||
"to use as the backing store for Java Heap.") \
|
"to use as the backing store for Java Heap.") \
|
||||||
\
|
\
|
||||||
|
product_pd(bool, VMContinuations, EXPERIMENTAL, \
|
||||||
|
"Enable VM continuations support") \
|
||||||
|
\
|
||||||
develop(bool, LoomDeoptAfterThaw, false, \
|
develop(bool, LoomDeoptAfterThaw, false, \
|
||||||
"Deopt stack after thaw") \
|
"Deopt stack after thaw") \
|
||||||
\
|
\
|
||||||
|
@ -368,6 +368,19 @@ void ThreadService::reset_contention_time_stat(JavaThread* thread) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ThreadService::is_virtual_or_carrier_thread(JavaThread* jt) {
|
||||||
|
oop threadObj = jt->threadObj();
|
||||||
|
if (threadObj != NULL && threadObj->is_a(vmClasses::BasicVirtualThread_klass())) {
|
||||||
|
// a virtual thread backed by JavaThread
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (jt->is_vthread_mounted()) {
|
||||||
|
// carrier thread
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Find deadlocks involving raw monitors, object monitors and concurrent locks
|
// Find deadlocks involving raw monitors, object monitors and concurrent locks
|
||||||
// if concurrent_locks is true.
|
// if concurrent_locks is true.
|
||||||
// We skip virtual thread carriers under the assumption that the current scheduler, ForkJoinPool,
|
// We skip virtual thread carriers under the assumption that the current scheduler, ForkJoinPool,
|
||||||
@ -388,15 +401,19 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list,
|
|||||||
// Initialize the depth-first-number for each JavaThread.
|
// Initialize the depth-first-number for each JavaThread.
|
||||||
JavaThreadIterator jti(t_list);
|
JavaThreadIterator jti(t_list);
|
||||||
for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
|
for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
|
||||||
if (jt->is_vthread_mounted()) continue;
|
if (!is_virtual_or_carrier_thread(jt)) {
|
||||||
jt->set_depth_first_number(-1);
|
jt->set_depth_first_number(-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeadlockCycle* deadlocks = NULL;
|
DeadlockCycle* deadlocks = NULL;
|
||||||
DeadlockCycle* last = NULL;
|
DeadlockCycle* last = NULL;
|
||||||
DeadlockCycle* cycle = new DeadlockCycle();
|
DeadlockCycle* cycle = new DeadlockCycle();
|
||||||
for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
|
for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
|
||||||
if (jt->is_vthread_mounted()) continue;
|
if (is_virtual_or_carrier_thread(jt)) {
|
||||||
|
// skip virtual and carrier threads
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (jt->depth_first_number() >= 0) {
|
if (jt->depth_first_number() >= 0) {
|
||||||
// this thread was already visited
|
// this thread was already visited
|
||||||
continue;
|
continue;
|
||||||
@ -471,7 +488,7 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentThread == NULL || currentThread->is_vthread_mounted()) {
|
if (currentThread == NULL || is_virtual_or_carrier_thread(currentThread)) {
|
||||||
// No dependency on another thread
|
// No dependency on another thread
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,9 @@ private:
|
|||||||
|
|
||||||
static void decrement_thread_counts(JavaThread* jt, bool daemon);
|
static void decrement_thread_counts(JavaThread* jt, bool daemon);
|
||||||
|
|
||||||
|
// test if the JavaThread is a virtual thread or has a mounted virtual thread
|
||||||
|
static bool is_virtual_or_carrier_thread(JavaThread* jt);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void init();
|
static void init();
|
||||||
static void add_thread(JavaThread* thread, bool daemon);
|
static void add_thread(JavaThread* thread, bool daemon);
|
||||||
|
67
src/java.base/share/classes/java/lang/BaseVirtualThread.java
Normal file
67
src/java.base/share/classes/java/lang/BaseVirtualThread.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package java.lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for virtual thread implementations.
|
||||||
|
*/
|
||||||
|
sealed abstract class BaseVirtualThread extends Thread
|
||||||
|
permits VirtualThread, ThreadBuilders.BoundVirtualThread {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a virtual Thread.
|
||||||
|
*
|
||||||
|
* @param name thread name, can be null
|
||||||
|
* @param characteristics thread characteristics
|
||||||
|
* @param bound true when bound to an OS thread
|
||||||
|
*/
|
||||||
|
BaseVirtualThread(String name, int characteristics, boolean bound) {
|
||||||
|
super(name, characteristics, bound);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parks the current virtual thread until the parking permit is available or
|
||||||
|
* the thread is interrupted.
|
||||||
|
*
|
||||||
|
* The behavior of this method when the current thread is not this thread
|
||||||
|
* is not defined.
|
||||||
|
*/
|
||||||
|
abstract void park();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parks current virtual thread up to the given waiting time until the parking
|
||||||
|
* permit is available or the thread is interrupted.
|
||||||
|
*
|
||||||
|
* The behavior of this method when the current thread is not this thread
|
||||||
|
* is not defined.
|
||||||
|
*/
|
||||||
|
abstract void parkNanos(long nanos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes available the parking permit to the given this virtual thread.
|
||||||
|
*/
|
||||||
|
abstract void unpark();
|
||||||
|
}
|
||||||
|
|
@ -2591,18 +2591,28 @@ public final class System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void parkVirtualThread() {
|
public void parkVirtualThread() {
|
||||||
VirtualThread.park();
|
Thread thread = Thread.currentThread();
|
||||||
|
if (thread instanceof BaseVirtualThread vthread) {
|
||||||
|
vthread.park();
|
||||||
|
} else {
|
||||||
|
throw new WrongThreadException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parkVirtualThread(long nanos) {
|
public void parkVirtualThread(long nanos) {
|
||||||
VirtualThread.parkNanos(nanos);
|
Thread thread = Thread.currentThread();
|
||||||
|
if (thread instanceof BaseVirtualThread vthread) {
|
||||||
|
vthread.parkNanos(nanos);
|
||||||
|
} else {
|
||||||
|
throw new WrongThreadException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unparkVirtualThread(Thread thread) {
|
public void unparkVirtualThread(Thread thread) {
|
||||||
if (thread instanceof VirtualThread vthread) {
|
if (thread instanceof BaseVirtualThread vthread) {
|
||||||
vthread.unpark();
|
vthread.unpark();
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Not a virtual thread");
|
throw new WrongThreadException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,11 @@ import java.security.ProtectionDomain;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.locks.LockSupport;
|
import java.util.concurrent.locks.LockSupport;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import jdk.internal.event.ThreadSleepEvent;
|
import jdk.internal.event.ThreadSleepEvent;
|
||||||
import jdk.internal.javac.PreviewFeature;
|
import jdk.internal.javac.PreviewFeature;
|
||||||
import jdk.internal.misc.PreviewFeatures;
|
import jdk.internal.misc.PreviewFeatures;
|
||||||
@ -736,8 +739,9 @@ public class Thread implements Runnable {
|
|||||||
*
|
*
|
||||||
* @param name thread name, can be null
|
* @param name thread name, can be null
|
||||||
* @param characteristics thread characteristics
|
* @param characteristics thread characteristics
|
||||||
|
* @param bound true when bound to an OS thread
|
||||||
*/
|
*/
|
||||||
Thread(String name, int characteristics) {
|
Thread(String name, int characteristics, boolean bound) {
|
||||||
this.tid = ThreadIdentifiers.next();
|
this.tid = ThreadIdentifiers.next();
|
||||||
this.name = (name != null) ? name : "";
|
this.name = (name != null) ? name : "";
|
||||||
this.inheritedAccessControlContext = Constants.NO_PERMISSIONS_ACC;
|
this.inheritedAccessControlContext = Constants.NO_PERMISSIONS_ACC;
|
||||||
@ -767,8 +771,14 @@ public class Thread implements Runnable {
|
|||||||
this.contextClassLoader = ClassLoader.getSystemClassLoader();
|
this.contextClassLoader = ClassLoader.getSystemClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// no additional fields
|
// create a FieldHolder object, needed when bound to an OS thread
|
||||||
this.holder = null;
|
if (bound) {
|
||||||
|
ThreadGroup g = Constants.VTHREAD_GROUP;
|
||||||
|
int pri = NORM_PRIORITY;
|
||||||
|
this.holder = new FieldHolder(g, null, -1, pri, true);
|
||||||
|
} else {
|
||||||
|
this.holder = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1495,8 +1505,9 @@ public class Thread implements Runnable {
|
|||||||
*/
|
*/
|
||||||
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
|
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
|
||||||
public static Thread startVirtualThread(Runnable task) {
|
public static Thread startVirtualThread(Runnable task) {
|
||||||
|
Objects.requireNonNull(task);
|
||||||
PreviewFeatures.ensureEnabled();
|
PreviewFeatures.ensureEnabled();
|
||||||
var thread = new VirtualThread(null, null, 0, task);
|
var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
|
||||||
thread.start();
|
thread.start();
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
@ -1511,7 +1522,7 @@ public class Thread implements Runnable {
|
|||||||
*/
|
*/
|
||||||
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
|
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
|
||||||
public final boolean isVirtual() {
|
public final boolean isVirtual() {
|
||||||
return (this instanceof VirtualThread);
|
return (this instanceof BaseVirtualThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2617,8 +2628,10 @@ public class Thread implements Runnable {
|
|||||||
StackTraceElement[][] traces = dumpThreads(threads);
|
StackTraceElement[][] traces = dumpThreads(threads);
|
||||||
Map<Thread, StackTraceElement[]> m = HashMap.newHashMap(threads.length);
|
Map<Thread, StackTraceElement[]> m = HashMap.newHashMap(threads.length);
|
||||||
for (int i = 0; i < threads.length; i++) {
|
for (int i = 0; i < threads.length; i++) {
|
||||||
|
Thread thread = threads[i];
|
||||||
StackTraceElement[] stackTrace = traces[i];
|
StackTraceElement[] stackTrace = traces[i];
|
||||||
if (stackTrace != null) {
|
// BoundVirtualThread objects may be in list returned by the VM
|
||||||
|
if (!thread.isVirtual() && stackTrace != null) {
|
||||||
m.put(threads[i], stackTrace);
|
m.put(threads[i], stackTrace);
|
||||||
}
|
}
|
||||||
// else terminated so we don't put it in the map
|
// else terminated so we don't put it in the map
|
||||||
@ -2688,7 +2701,11 @@ public class Thread implements Runnable {
|
|||||||
* Return an array of all live threads.
|
* Return an array of all live threads.
|
||||||
*/
|
*/
|
||||||
static Thread[] getAllThreads() {
|
static Thread[] getAllThreads() {
|
||||||
return getThreads();
|
Thread[] threads = getThreads();
|
||||||
|
return Stream.of(threads)
|
||||||
|
// BoundVirtualThread objects may be in list returned by the VM
|
||||||
|
.filter(Predicate.not(Thread::isVirtual))
|
||||||
|
.toArray(Thread[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native StackTraceElement[][] dumpThreads(Thread[] threads);
|
private static native StackTraceElement[][] dumpThreads(Thread[] threads);
|
||||||
|
@ -30,9 +30,12 @@ import java.lang.Thread.Builder.OfVirtual;
|
|||||||
import java.lang.Thread.UncaughtExceptionHandler;
|
import java.lang.Thread.UncaughtExceptionHandler;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
|
import jdk.internal.vm.ContinuationSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines static methods to create platform and virtual thread builders.
|
* Defines static methods to create platform and virtual thread builders.
|
||||||
@ -133,6 +136,9 @@ class ThreadBuilders {
|
|||||||
private int priority;
|
private int priority;
|
||||||
private long stackSize;
|
private long stackSize;
|
||||||
|
|
||||||
|
PlatformThreadBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String nextThreadName() {
|
String nextThreadName() {
|
||||||
String name = super.nextThreadName();
|
String name = super.nextThreadName();
|
||||||
@ -203,12 +209,22 @@ class ThreadBuilders {
|
|||||||
*/
|
*/
|
||||||
static final class VirtualThreadBuilder
|
static final class VirtualThreadBuilder
|
||||||
extends BaseThreadBuilder<OfVirtual> implements OfVirtual {
|
extends BaseThreadBuilder<OfVirtual> implements OfVirtual {
|
||||||
private Executor scheduler; // set by tests
|
private Executor scheduler;
|
||||||
|
|
||||||
|
VirtualThreadBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoked by tests
|
||||||
|
VirtualThreadBuilder(Executor scheduler) {
|
||||||
|
if (!ContinuationSupport.isSupported())
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
this.scheduler = Objects.requireNonNull(scheduler);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Thread unstarted(Runnable task) {
|
public Thread unstarted(Runnable task) {
|
||||||
Objects.requireNonNull(task);
|
Objects.requireNonNull(task);
|
||||||
var thread = new VirtualThread(scheduler, nextThreadName(), characteristics(), task);
|
var thread = newVirtualThread(scheduler, nextThreadName(), characteristics(), task);
|
||||||
UncaughtExceptionHandler uhe = uncaughtExceptionHandler();
|
UncaughtExceptionHandler uhe = uncaughtExceptionHandler();
|
||||||
if (uhe != null)
|
if (uhe != null)
|
||||||
thread.uncaughtExceptionHandler(uhe);
|
thread.uncaughtExceptionHandler(uhe);
|
||||||
@ -349,11 +365,82 @@ class ThreadBuilders {
|
|||||||
public Thread newThread(Runnable task) {
|
public Thread newThread(Runnable task) {
|
||||||
Objects.requireNonNull(task);
|
Objects.requireNonNull(task);
|
||||||
String name = nextThreadName();
|
String name = nextThreadName();
|
||||||
Thread thread = new VirtualThread(scheduler, name, characteristics(), task);
|
Thread thread = newVirtualThread(scheduler, name, characteristics(), task);
|
||||||
UncaughtExceptionHandler uhe = uncaughtExceptionHandler();
|
UncaughtExceptionHandler uhe = uncaughtExceptionHandler();
|
||||||
if (uhe != null)
|
if (uhe != null)
|
||||||
thread.uncaughtExceptionHandler(uhe);
|
thread.uncaughtExceptionHandler(uhe);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new virtual thread to run the given task.
|
||||||
|
*/
|
||||||
|
static Thread newVirtualThread(Executor scheduler,
|
||||||
|
String name,
|
||||||
|
int characteristics,
|
||||||
|
Runnable task) {
|
||||||
|
if (ContinuationSupport.isSupported()) {
|
||||||
|
return new VirtualThread(scheduler, name, characteristics, task);
|
||||||
|
} else {
|
||||||
|
if (scheduler != null)
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
return new BoundVirtualThread(name, characteristics, task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "virtual thread" that is backed by a platform thread. This implementation
|
||||||
|
* is intended for platforms that don't have the underlying VM support for
|
||||||
|
* continuations. It can also be used for testing.
|
||||||
|
*/
|
||||||
|
static final class BoundVirtualThread extends BaseVirtualThread {
|
||||||
|
private static final Unsafe U = Unsafe.getUnsafe();
|
||||||
|
private final Runnable task;
|
||||||
|
private boolean runInvoked;
|
||||||
|
|
||||||
|
BoundVirtualThread(String name, int characteristics, Runnable task) {
|
||||||
|
super(name, characteristics, true);
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// run is specified to do nothing when Thread is a virtual thread
|
||||||
|
if (Thread.currentThread() == this && !runInvoked) {
|
||||||
|
runInvoked = true;
|
||||||
|
task.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void park() {
|
||||||
|
U.park(false, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void parkNanos(long nanos) {
|
||||||
|
U.park(false, nanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void unpark() {
|
||||||
|
U.unpark(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder("VirtualThread[#");
|
||||||
|
sb.append(threadId());
|
||||||
|
String name = getName();
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
sb.append(",");
|
||||||
|
sb.append(name);
|
||||||
|
}
|
||||||
|
sb.append("]/");
|
||||||
|
String stateAsString = threadState().toString();
|
||||||
|
sb.append(stateAsString.toLowerCase(Locale.ROOT));
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ import static java.util.concurrent.TimeUnit.*;
|
|||||||
* A thread that is scheduled by the Java virtual machine rather than the operating
|
* A thread that is scheduled by the Java virtual machine rather than the operating
|
||||||
* system.
|
* system.
|
||||||
*/
|
*/
|
||||||
final class VirtualThread extends Thread {
|
final class VirtualThread extends BaseVirtualThread {
|
||||||
private static final Unsafe U = Unsafe.getUnsafe();
|
private static final Unsafe U = Unsafe.getUnsafe();
|
||||||
private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
|
private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
|
||||||
private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler();
|
private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler();
|
||||||
@ -148,7 +148,7 @@ final class VirtualThread extends Thread {
|
|||||||
* @param task the task to execute
|
* @param task the task to execute
|
||||||
*/
|
*/
|
||||||
VirtualThread(Executor scheduler, String name, int characteristics, Runnable task) {
|
VirtualThread(Executor scheduler, String name, int characteristics, Runnable task) {
|
||||||
super(name, characteristics);
|
super(name, characteristics, /*bound*/ false);
|
||||||
Objects.requireNonNull(task);
|
Objects.requireNonNull(task);
|
||||||
|
|
||||||
// choose scheduler if not specified
|
// choose scheduler if not specified
|
||||||
@ -480,23 +480,15 @@ final class VirtualThread extends Thread {
|
|||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parks the current virtual thread until unparked or interrupted.
|
|
||||||
*/
|
|
||||||
static void park() {
|
|
||||||
if (currentThread() instanceof VirtualThread vthread) {
|
|
||||||
vthread.doPark();
|
|
||||||
} else {
|
|
||||||
throw new WrongThreadException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parks until unparked or interrupted. If already unparked then the parking
|
* Parks until unparked or interrupted. If already unparked then the parking
|
||||||
* permit is consumed and this method completes immediately (meaning it doesn't
|
* permit is consumed and this method completes immediately (meaning it doesn't
|
||||||
* yield). It also completes immediately if the interrupt status is set.
|
* yield). It also completes immediately if the interrupt status is set.
|
||||||
*/
|
*/
|
||||||
private void doPark() {
|
@Override
|
||||||
|
void park() {
|
||||||
|
assert Thread.currentThread() == this;
|
||||||
|
|
||||||
// complete immediately if parking permit available or interrupted
|
// complete immediately if parking permit available or interrupted
|
||||||
if (getAndSetParkPermit(false) || interrupted)
|
if (getAndSetParkPermit(false) || interrupted)
|
||||||
return;
|
return;
|
||||||
@ -513,20 +505,6 @@ final class VirtualThread extends Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parks the current virtual thread up to the given waiting time or until
|
|
||||||
* unparked or interrupted.
|
|
||||||
*
|
|
||||||
* @param nanos the maximum number of nanoseconds to wait
|
|
||||||
*/
|
|
||||||
static void parkNanos(long nanos) {
|
|
||||||
if (currentThread() instanceof VirtualThread vthread) {
|
|
||||||
vthread.doParkNanos(nanos);
|
|
||||||
} else {
|
|
||||||
throw new WrongThreadException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parks up to the given waiting time or until unparked or interrupted.
|
* Parks up to the given waiting time or until unparked or interrupted.
|
||||||
* If already unparked then the parking permit is consumed and this method
|
* If already unparked then the parking permit is consumed and this method
|
||||||
@ -535,7 +513,8 @@ final class VirtualThread extends Thread {
|
|||||||
*
|
*
|
||||||
* @param nanos the maximum number of nanoseconds to wait.
|
* @param nanos the maximum number of nanoseconds to wait.
|
||||||
*/
|
*/
|
||||||
private void doParkNanos(long nanos) {
|
@Override
|
||||||
|
void parkNanos(long nanos) {
|
||||||
assert Thread.currentThread() == this;
|
assert Thread.currentThread() == this;
|
||||||
|
|
||||||
// complete immediately if parking permit available or interrupted
|
// complete immediately if parking permit available or interrupted
|
||||||
@ -638,6 +617,7 @@ final class VirtualThread extends Thread {
|
|||||||
* not to block.
|
* not to block.
|
||||||
* @throws RejectedExecutionException if the scheduler cannot accept a task
|
* @throws RejectedExecutionException if the scheduler cannot accept a task
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
@ChangesCurrentThread
|
@ChangesCurrentThread
|
||||||
void unpark() {
|
void unpark() {
|
||||||
Thread currentThread = Thread.currentThread();
|
Thread currentThread = Thread.currentThread();
|
||||||
|
@ -49,6 +49,7 @@ public class Continuation {
|
|||||||
private static final boolean PRESERVE_EXTENT_LOCAL_CACHE;
|
private static final boolean PRESERVE_EXTENT_LOCAL_CACHE;
|
||||||
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
||||||
static {
|
static {
|
||||||
|
ContinuationSupport.ensureSupported();
|
||||||
PreviewFeatures.ensureEnabled();
|
PreviewFeatures.ensureEnabled();
|
||||||
|
|
||||||
StackChunk.init(); // ensure StackChunk class is initialized
|
StackChunk.init(); // ensure StackChunk class is initialized
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package jdk.internal.vm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a static method to test if the VM has continuations support.
|
||||||
|
*/
|
||||||
|
public class ContinuationSupport {
|
||||||
|
private static final boolean SUPPORTED = isSupported0();
|
||||||
|
|
||||||
|
private ContinuationSupport() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the VM has continuations support.
|
||||||
|
*/
|
||||||
|
public static boolean isSupported() {
|
||||||
|
return SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that VM has continuations support.
|
||||||
|
* @throws UnsupportedOperationException if not supported
|
||||||
|
*/
|
||||||
|
public static void ensureSupported() {
|
||||||
|
if (!isSupported()) {
|
||||||
|
throw new UnsupportedOperationException("VM does not support continuations");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native boolean isSupported0();
|
||||||
|
}
|
34
src/java.base/share/native/libjava/ContinuationSupport.c
Normal file
34
src/java.base/share/native/libjava/ContinuationSupport.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jni.h"
|
||||||
|
#include "jvm.h"
|
||||||
|
|
||||||
|
#include "jdk_internal_misc_PreviewFeatures.h"
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_jdk_internal_vm_ContinuationSupport_isSupported0(JNIEnv *env, jclass cls) {
|
||||||
|
return JVM_IsContinuationsSupported();
|
||||||
|
}
|
@ -23,12 +23,12 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
|
|
||||||
#include "jdk_internal_misc_PreviewFeatures.h"
|
#include "jdk_internal_misc_PreviewFeatures.h"
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_jdk_internal_misc_PreviewFeatures_isPreviewEnabled(JNIEnv *env, jclass cls) {
|
Java_jdk_internal_misc_PreviewFeatures_isPreviewEnabled(JNIEnv *env, jclass cls) {
|
||||||
return JVM_IsPreviewEnabled(env);
|
return JVM_IsPreviewEnabled();
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import javax.management.openmbean.ArrayType;
|
|||||||
import javax.management.openmbean.CompositeData;
|
import javax.management.openmbean.CompositeData;
|
||||||
import sun.management.ManagementFactoryHelper;
|
import sun.management.ManagementFactoryHelper;
|
||||||
import sun.management.ThreadInfoCompositeData;
|
import sun.management.ThreadInfoCompositeData;
|
||||||
|
import sun.management.Util;
|
||||||
import static java.lang.Thread.State.*;
|
import static java.lang.Thread.State.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,6 +94,7 @@ import static java.lang.Thread.State.*;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class ThreadInfo {
|
public class ThreadInfo {
|
||||||
|
private boolean virtual; // accessed by ThreadImpl
|
||||||
private String threadName;
|
private String threadName;
|
||||||
private long threadId;
|
private long threadId;
|
||||||
private long blockedTime;
|
private long blockedTime;
|
||||||
@ -224,6 +226,7 @@ public class ThreadInfo {
|
|||||||
StackTraceElement[] stackTrace,
|
StackTraceElement[] stackTrace,
|
||||||
MonitorInfo[] lockedMonitors,
|
MonitorInfo[] lockedMonitors,
|
||||||
LockInfo[] lockedSynchronizers) {
|
LockInfo[] lockedSynchronizers) {
|
||||||
|
this.virtual = Util.isVirtual(t);
|
||||||
this.threadId = t.threadId();
|
this.threadId = t.threadId();
|
||||||
this.threadName = t.getName();
|
this.threadName = t.getName();
|
||||||
this.threadState = ManagementFactoryHelper.toThreadState(state);
|
this.threadState = ManagementFactoryHelper.toThreadState(state);
|
||||||
|
@ -28,14 +28,10 @@ package sun.management;
|
|||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.ThreadInfo;
|
import java.lang.management.ThreadInfo;
|
||||||
import java.lang.management.ThreadMXBean;
|
import java.lang.management.ThreadMXBean;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedActionException;
|
|
||||||
import java.security.PrivilegedExceptionAction;
|
|
||||||
import javax.management.ObjectName;
|
import javax.management.ObjectName;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import sun.management.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for java.lang.management.ThreadMXBean as well as providing the
|
* Implementation for java.lang.management.ThreadMXBean as well as providing the
|
||||||
@ -134,31 +130,24 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
@Override
|
@Override
|
||||||
public long[] getAllThreadIds() {
|
public long[] getAllThreadIds() {
|
||||||
Util.checkMonitorAccess();
|
Util.checkMonitorAccess();
|
||||||
|
|
||||||
Thread[] threads = getThreads();
|
Thread[] threads = getThreads();
|
||||||
int length = threads.length;
|
return platformThreadIds(threads);
|
||||||
long[] ids = new long[length];
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
Thread t = threads[i];
|
|
||||||
ids[i] = t.threadId();
|
|
||||||
}
|
|
||||||
return ids;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThreadInfo getThreadInfo(long id) {
|
public ThreadInfo getThreadInfo(long id) {
|
||||||
long[] ids = new long[1];
|
return getThreadInfo(id, 0);
|
||||||
ids[0] = id;
|
|
||||||
final ThreadInfo[] infos = getThreadInfo(ids, 0);
|
|
||||||
return infos[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThreadInfo getThreadInfo(long id, int maxDepth) {
|
public ThreadInfo getThreadInfo(long id, int maxDepth) {
|
||||||
long[] ids = new long[1];
|
long[] ids = new long[] { id };
|
||||||
ids[0] = id;
|
ThreadInfo ti = getThreadInfo(ids, maxDepth)[0];
|
||||||
final ThreadInfo[] infos = getThreadInfo(ids, maxDepth);
|
if (ti == null || Util.isVirtual(ti)) {
|
||||||
return infos[0];
|
return null;
|
||||||
|
} else {
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -202,6 +191,7 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
} else {
|
} else {
|
||||||
getThreadInfo1(ids, maxDepth, infos);
|
getThreadInfo1(ids, maxDepth, infos);
|
||||||
}
|
}
|
||||||
|
nullVirtualThreads(infos);
|
||||||
return infos;
|
return infos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +222,7 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
|
|
||||||
private boolean verifyCurrentThreadCpuTime() {
|
private boolean verifyCurrentThreadCpuTime() {
|
||||||
// check if Thread CPU time measurement is supported.
|
// check if Thread CPU time measurement is supported.
|
||||||
if (isVirtual(Thread.currentThread())) {
|
if (Util.isVirtual(Thread.currentThread())) {
|
||||||
throw new UnsupportedOperationException("Not supported by virtual threads");
|
throw new UnsupportedOperationException("Not supported by virtual threads");
|
||||||
}
|
}
|
||||||
if (!isCurrentThreadCpuTimeSupported()) {
|
if (!isCurrentThreadCpuTimeSupported()) {
|
||||||
@ -294,7 +284,7 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
long id = ids[0];
|
long id = ids[0];
|
||||||
Thread thread = Thread.currentThread();
|
Thread thread = Thread.currentThread();
|
||||||
if (id == thread.threadId()) {
|
if (id == thread.threadId()) {
|
||||||
if (isVirtual(thread)) {
|
if (Util.isVirtual(thread)) {
|
||||||
times[0] = -1;
|
times[0] = -1;
|
||||||
} else {
|
} else {
|
||||||
times[0] = getThreadTotalCpuTime0(0);
|
times[0] = getThreadTotalCpuTime0(0);
|
||||||
@ -337,7 +327,7 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
long id = ids[0];
|
long id = ids[0];
|
||||||
Thread thread = Thread.currentThread();
|
Thread thread = Thread.currentThread();
|
||||||
if (id == thread.threadId()) {
|
if (id == thread.threadId()) {
|
||||||
if (isVirtual(thread)) {
|
if (Util.isVirtual(thread)) {
|
||||||
times[0] = -1;
|
times[0] = -1;
|
||||||
} else {
|
} else {
|
||||||
times[0] = getThreadUserCpuTime0(0);
|
times[0] = getThreadUserCpuTime0(0);
|
||||||
@ -371,7 +361,7 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected long getCurrentThreadAllocatedBytes() {
|
protected long getCurrentThreadAllocatedBytes() {
|
||||||
if (isThreadAllocatedMemoryEnabled() && !isVirtual(Thread.currentThread())) {
|
if (isThreadAllocatedMemoryEnabled() && !Util.isVirtual(Thread.currentThread())) {
|
||||||
return getThreadAllocatedMemory0(0);
|
return getThreadAllocatedMemory0(0);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -387,7 +377,7 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
if (verified) {
|
if (verified) {
|
||||||
Thread thread = Thread.currentThread();
|
Thread thread = Thread.currentThread();
|
||||||
if (id == thread.threadId()) {
|
if (id == thread.threadId()) {
|
||||||
if (isVirtual(thread)) {
|
if (Util.isVirtual(thread)) {
|
||||||
return -1L;
|
return -1L;
|
||||||
} else {
|
} else {
|
||||||
return getThreadAllocatedMemory0(0);
|
return getThreadAllocatedMemory0(0);
|
||||||
@ -443,9 +433,7 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
*/
|
*/
|
||||||
private long[] threadsToIds(Thread[] threads) {
|
private long[] threadsToIds(Thread[] threads) {
|
||||||
if (threads != null) {
|
if (threads != null) {
|
||||||
long[] tids = Stream.of(threads)
|
long[] tids = platformThreadIds(threads);
|
||||||
.mapToLong(Thread::threadId)
|
|
||||||
.toArray();
|
|
||||||
if (tids.length > 0) {
|
if (tids.length > 0) {
|
||||||
return tids;
|
return tids;
|
||||||
}
|
}
|
||||||
@ -509,8 +497,10 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
public ThreadInfo[] getThreadInfo(long[] ids,
|
public ThreadInfo[] getThreadInfo(long[] ids,
|
||||||
boolean lockedMonitors,
|
boolean lockedMonitors,
|
||||||
boolean lockedSynchronizers) {
|
boolean lockedSynchronizers) {
|
||||||
return dumpThreads0(ids, lockedMonitors, lockedSynchronizers,
|
ThreadInfo[] infos = dumpThreads0(ids, lockedMonitors, lockedSynchronizers,
|
||||||
Integer.MAX_VALUE);
|
Integer.MAX_VALUE);
|
||||||
|
nullVirtualThreads(infos);
|
||||||
|
return infos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadInfo[] getThreadInfo(long[] ids,
|
public ThreadInfo[] getThreadInfo(long[] ids,
|
||||||
@ -527,14 +517,17 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
if (ids.length == 0) return new ThreadInfo[0];
|
if (ids.length == 0) return new ThreadInfo[0];
|
||||||
|
|
||||||
verifyDumpThreads(lockedMonitors, lockedSynchronizers);
|
verifyDumpThreads(lockedMonitors, lockedSynchronizers);
|
||||||
return dumpThreads0(ids, lockedMonitors, lockedSynchronizers, maxDepth);
|
ThreadInfo[] infos = dumpThreads0(ids, lockedMonitors, lockedSynchronizers, maxDepth);
|
||||||
|
nullVirtualThreads(infos);
|
||||||
|
return infos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
|
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
|
||||||
boolean lockedSynchronizers) {
|
boolean lockedSynchronizers) {
|
||||||
return dumpAllThreads(lockedMonitors, lockedSynchronizers,
|
ThreadInfo[] infos = dumpAllThreads(lockedMonitors, lockedSynchronizers,
|
||||||
Integer.MAX_VALUE);
|
Integer.MAX_VALUE);
|
||||||
|
return platformThreads(infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
|
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
|
||||||
@ -545,7 +538,8 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
"Invalid maxDepth parameter: " + maxDepth);
|
"Invalid maxDepth parameter: " + maxDepth);
|
||||||
}
|
}
|
||||||
verifyDumpThreads(lockedMonitors, lockedSynchronizers);
|
verifyDumpThreads(lockedMonitors, lockedSynchronizers);
|
||||||
return dumpThreads0(null, lockedMonitors, lockedSynchronizers, maxDepth);
|
ThreadInfo[] infos = dumpThreads0(null, lockedMonitors, lockedSynchronizers, maxDepth);
|
||||||
|
return platformThreads(infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VM support where maxDepth == -1 to request entire stack dump
|
// VM support where maxDepth == -1 to request entire stack dump
|
||||||
@ -579,29 +573,34 @@ public class ThreadImpl implements ThreadMXBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the given Thread is a virutal thread.
|
* Returns the thread identifiers of the platform threads in the given array.
|
||||||
*
|
|
||||||
* @implNote This method uses reflection because Thread::isVirtual is a preview API
|
|
||||||
* and the java.management cannot be compiled with --enable-preview.
|
|
||||||
*/
|
*/
|
||||||
private static boolean isVirtual(Thread thread) {
|
private static long[] platformThreadIds(Thread[] threads) {
|
||||||
try {
|
return Stream.of(threads)
|
||||||
return (boolean) IS_VIRTUAL.invoke(thread);
|
.filter(t -> !Util.isVirtual(t))
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
.mapToLong(Thread::threadId)
|
||||||
throw new InternalError(e);
|
.toArray();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final Method IS_VIRTUAL;
|
/**
|
||||||
static {
|
* Returns the ThreadInfo objects from the given array that correspond to platform
|
||||||
try {
|
* threads.
|
||||||
PrivilegedExceptionAction<Method> pa = () -> Thread.class.getMethod("isVirtual");
|
*/
|
||||||
@SuppressWarnings("removal")
|
private ThreadInfo[] platformThreads(ThreadInfo[] infos) {
|
||||||
Method m = AccessController.doPrivileged(pa);
|
return Stream.of(infos)
|
||||||
IS_VIRTUAL = m;
|
.filter(ti -> !Util.isVirtual(ti))
|
||||||
} catch (PrivilegedActionException e) {
|
.toArray(ThreadInfo[]::new);
|
||||||
throw new InternalError(e);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the elements of the given array to null if they correspond to a virtual thread.
|
||||||
|
*/
|
||||||
|
private static void nullVirtualThreads(ThreadInfo[] infos) {
|
||||||
|
for (int i = 0; i < infos.length; i++) {
|
||||||
|
ThreadInfo ti = infos[i];
|
||||||
|
if (ti != null && Util.isVirtual(ti)) {
|
||||||
|
infos[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,13 @@
|
|||||||
|
|
||||||
package sun.management;
|
package sun.management;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.management.ManagementPermission;
|
import java.lang.management.ManagementPermission;
|
||||||
|
import java.lang.management.ThreadInfo;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.management.ObjectName;
|
import javax.management.ObjectName;
|
||||||
import javax.management.MalformedObjectNameException;
|
import javax.management.MalformedObjectNameException;
|
||||||
@ -81,4 +87,56 @@ public class Util {
|
|||||||
public static void checkControlAccess() throws SecurityException {
|
public static void checkControlAccess() throws SecurityException {
|
||||||
checkAccess(controlPermission);
|
checkAccess(controlPermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given Thread is a virtual thread.
|
||||||
|
*
|
||||||
|
* @implNote This method uses reflection because Thread::isVirtual is a preview API
|
||||||
|
* and the java.management module cannot be compiled with --enable-preview.
|
||||||
|
*/
|
||||||
|
public static boolean isVirtual(Thread thread) {
|
||||||
|
try {
|
||||||
|
return (boolean) THREAD_IS_VIRTUAL.invoke(thread);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InternalError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given ThreadInfo is for a virtual thread.
|
||||||
|
*/
|
||||||
|
public static boolean isVirtual(ThreadInfo threadInfo) {
|
||||||
|
try {
|
||||||
|
return (boolean) THREADINFO_VIRTUAL.get(threadInfo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InternalError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
private static Method threadIsVirtual() {
|
||||||
|
PrivilegedExceptionAction<Method> pa = () -> Thread.class.getMethod("isVirtual");
|
||||||
|
try {
|
||||||
|
return AccessController.doPrivileged(pa);
|
||||||
|
} catch (PrivilegedActionException e) {
|
||||||
|
throw new InternalError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
private static Field threadInfoVirtual() {
|
||||||
|
PrivilegedExceptionAction<Field> pa = () -> {
|
||||||
|
Field f = ThreadInfo.class.getDeclaredField("virtual");
|
||||||
|
f.setAccessible(true);
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
return AccessController.doPrivileged(pa);
|
||||||
|
} catch (PrivilegedActionException e) {
|
||||||
|
throw new InternalError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Method THREAD_IS_VIRTUAL = threadIsVirtual();
|
||||||
|
private static final Field THREADINFO_VIRTUAL = threadInfoVirtual();
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ requires.properties= \
|
|||||||
vm.cds \
|
vm.cds \
|
||||||
vm.cds.custom.loaders \
|
vm.cds.custom.loaders \
|
||||||
vm.cds.write.archived.java.heap \
|
vm.cds.write.archived.java.heap \
|
||||||
|
vm.continuations \
|
||||||
vm.jvmti \
|
vm.jvmti \
|
||||||
vm.graal.enabled \
|
vm.graal.enabled \
|
||||||
vm.compiler1.enabled \
|
vm.compiler1.enabled \
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
* @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
|
* @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
|
||||||
* make sure class redefinition works with CDS.
|
* make sure class redefinition works with CDS.
|
||||||
* @requires vm.cds
|
* @requires vm.cds
|
||||||
|
* @requires vm.continuations
|
||||||
* @requires vm.jvmti
|
* @requires vm.jvmti
|
||||||
* @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds
|
* @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds
|
||||||
* @run driver RedefineClassHelper
|
* @run driver RedefineClassHelper
|
||||||
|
@ -26,7 +26,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test JNIMonitor
|
* @test JNIMonitor
|
||||||
* @summary Tests that JNI monitors works correctly for native threads
|
* @summary Tests that JNI monitors work correctly with virtual threads
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} JNIMonitor.java
|
* @compile --enable-preview -source ${jdk.version} JNIMonitor.java
|
||||||
* @run main/native/othervm --enable-preview JNIMonitor
|
* @run main/native/othervm --enable-preview JNIMonitor
|
||||||
|
@ -83,7 +83,7 @@ public class framecnt01 {
|
|||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
|
|
||||||
// this is too fragile, implementation can change at any time.
|
// this is too fragile, implementation can change at any time.
|
||||||
checkFrames(vThread1, false, 15);
|
checkFrames(vThread1, false, 14);
|
||||||
LockSupport.unpark(vThread1);
|
LockSupport.unpark(vThread1);
|
||||||
vThread1.join();
|
vThread1.join();
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ requires.properties= \
|
|||||||
vm.compiler1.enabled \
|
vm.compiler1.enabled \
|
||||||
vm.compiler2.enabled \
|
vm.compiler2.enabled \
|
||||||
vm.cds \
|
vm.cds \
|
||||||
|
vm.continuations \
|
||||||
vm.musl \
|
vm.musl \
|
||||||
vm.debug \
|
vm.debug \
|
||||||
vm.hasSA \
|
vm.hasSA \
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
* @test
|
* @test
|
||||||
* @bug 8234808
|
* @bug 8234808
|
||||||
*
|
*
|
||||||
|
* @requires vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @run main/othervm JdbOptions
|
* @run main/othervm JdbOptions
|
||||||
*/
|
*/
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Test virtual threads using a custom scheduler
|
* @summary Test virtual threads using a custom scheduler
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.base/java.lang:+open
|
* @modules java.base/java.lang:+open
|
||||||
* @compile --enable-preview -source ${jdk.version} CustomScheduler.java
|
* @compile --enable-preview -source ${jdk.version} CustomScheduler.java
|
||||||
* @run testng/othervm --enable-preview CustomScheduler
|
* @run testng/othervm --enable-preview CustomScheduler
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Test Thread::getStackTrace on a virtual thread that is runnable-unmounted
|
* @summary Test Thread::getStackTrace on a virtual thread that is runnable-unmounted
|
||||||
|
* @requires vm.continuations
|
||||||
* @compile --enable-preview -source ${jdk.version} GetStackTraceWhenRunnable.java
|
* @compile --enable-preview -source ${jdk.version} GetStackTraceWhenRunnable.java
|
||||||
* @run main/othervm --enable-preview -Djdk.virtualThreadScheduler.maxPoolSize=1 GetStackTraceWhenRunnable
|
* @run main/othervm --enable-preview -Djdk.virtualThreadScheduler.maxPoolSize=1 GetStackTraceWhenRunnable
|
||||||
*/
|
*/
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Test Thread.holdsLock when lock held by carrier thread
|
* @summary Test Thread.holdsLock when lock held by carrier thread
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.base/java.lang:+open
|
* @modules java.base/java.lang:+open
|
||||||
* @compile --enable-preview -source ${jdk.version} HoldsLock.java
|
* @compile --enable-preview -source ${jdk.version} HoldsLock.java
|
||||||
* @run testng/othervm --enable-preview HoldsLock
|
* @run testng/othervm --enable-preview HoldsLock
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Basic test for JFR jdk.VirtualThreadXXX events.
|
* @summary Basic test for JFR jdk.VirtualThreadXXX events
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules jdk.jfr java.base/java.lang:+open
|
* @modules jdk.jfr java.base/java.lang:+open
|
||||||
* @compile --enable-preview -source ${jdk.version} JfrEvents.java
|
* @compile --enable-preview -source ${jdk.version} JfrEvents.java
|
||||||
* @run testng/othervm --enable-preview JfrEvents
|
* @run testng/othervm --enable-preview JfrEvents
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @summary Test virtual thread park when scheduler is a fixed thread pool
|
* @summary Test virtual thread park when scheduler is a fixed thread pool
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.base/java.lang:+open
|
* @modules java.base/java.lang:+open
|
||||||
* @compile --enable-preview -source ${jdk.version} ParkWithFixedThreadPool.java
|
* @compile --enable-preview -source ${jdk.version} ParkWithFixedThreadPool.java
|
||||||
* @run testng/othervm --enable-preview ParkWithFixedThreadPool
|
* @run testng/othervm --enable-preview ParkWithFixedThreadPool
|
||||||
|
@ -39,6 +39,7 @@ import java.util.concurrent.ThreadFactory;
|
|||||||
import java.util.concurrent.locks.LockSupport;
|
import java.util.concurrent.locks.LockSupport;
|
||||||
|
|
||||||
import jdk.test.lib.thread.VThreadRunner;
|
import jdk.test.lib.thread.VThreadRunner;
|
||||||
|
import org.testng.SkipException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
@ -141,10 +142,12 @@ public class Reflection {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testInvokeStatic6() throws Exception {
|
public void testInvokeStatic6() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
Method parkMethod = Parker.class.getDeclaredMethod("park");
|
Method parkMethod = Parker.class.getDeclaredMethod("park");
|
||||||
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
||||||
ThreadFactory factory = ThreadBuilders.virtualThreadBuilder(scheduler).factory();
|
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
||||||
|
ThreadFactory factory = builder.factory();
|
||||||
Thread vthread = factory.newThread(() -> {
|
Thread vthread = factory.newThread(() -> {
|
||||||
try {
|
try {
|
||||||
parkMethod.invoke(null); // blocks
|
parkMethod.invoke(null); // blocks
|
||||||
@ -315,10 +318,12 @@ public class Reflection {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testNewInstance6() throws Exception {
|
public void testNewInstance6() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
Constructor<?> ctor = Parker.class.getDeclaredConstructor();
|
Constructor<?> ctor = Parker.class.getDeclaredConstructor();
|
||||||
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
||||||
ThreadFactory factory = ThreadBuilders.virtualThreadBuilder(scheduler).factory();
|
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
||||||
|
ThreadFactory factory = builder.factory();
|
||||||
Thread vthread = factory.newThread(() -> {
|
Thread vthread = factory.newThread(() -> {
|
||||||
try {
|
try {
|
||||||
ctor.newInstance();
|
ctor.newInstance();
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
* @test
|
* @test
|
||||||
* @summary Test stack traces in exceptions and stack frames waslked by the StackWalker
|
* @summary Test stack traces in exceptions and stack frames waslked by the StackWalker
|
||||||
* API do not include the carrier stack frames
|
* API do not include the carrier stack frames
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.management
|
* @modules java.management
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} StackTraces.java
|
* @compile --enable-preview -source ${jdk.version} StackTraces.java
|
||||||
|
@ -31,6 +31,15 @@
|
|||||||
* @run testng/othervm/timeout=300 ThreadAPI
|
* @run testng/othervm/timeout=300 ThreadAPI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @requires vm.continuations
|
||||||
|
* @enablePreview
|
||||||
|
* @modules java.base/java.lang:+open
|
||||||
|
* @library /test/lib
|
||||||
|
* @run testng/othervm/timeout=300 -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations ThreadAPI
|
||||||
|
*/
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -53,6 +62,7 @@ import java.util.stream.Stream;
|
|||||||
import java.nio.channels.Selector;
|
import java.nio.channels.Selector;
|
||||||
|
|
||||||
import jdk.test.lib.thread.VThreadRunner;
|
import jdk.test.lib.thread.VThreadRunner;
|
||||||
|
import org.testng.SkipException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
@ -1085,6 +1095,8 @@ public class ThreadAPI {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testYield1() throws Exception {
|
public void testYield1() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
var list = new CopyOnWriteArrayList<String>();
|
var list = new CopyOnWriteArrayList<String>();
|
||||||
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
||||||
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
||||||
@ -1112,6 +1124,8 @@ public class ThreadAPI {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testYield2() throws Exception {
|
public void testYield2() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
var list = new CopyOnWriteArrayList<String>();
|
var list = new CopyOnWriteArrayList<String>();
|
||||||
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
||||||
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
||||||
@ -1687,6 +1701,8 @@ public class ThreadAPI {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetState3() throws Exception {
|
public void testGetState3() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
AtomicBoolean completed = new AtomicBoolean();
|
AtomicBoolean completed = new AtomicBoolean();
|
||||||
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
|
||||||
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
|
||||||
@ -1853,6 +1869,8 @@ public class ThreadAPI {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetStackTrace2() throws Exception {
|
public void testGetStackTrace2() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("Requires continuations support");
|
||||||
List<Thread> threads = new ArrayList<>();
|
List<Thread> threads = new ArrayList<>();
|
||||||
AtomicBoolean done = new AtomicBoolean();
|
AtomicBoolean done = new AtomicBoolean();
|
||||||
try {
|
try {
|
||||||
@ -1914,6 +1932,8 @@ public class ThreadAPI {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetStackTrace4() throws Exception {
|
public void testGetStackTrace4() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
try (ForkJoinPool pool = new ForkJoinPool(1)) {
|
try (ForkJoinPool pool = new ForkJoinPool(1)) {
|
||||||
AtomicReference<Thread> ref = new AtomicReference<>();
|
AtomicReference<Thread> ref = new AtomicReference<>();
|
||||||
Executor scheduler = task -> {
|
Executor scheduler = task -> {
|
||||||
@ -2010,6 +2030,8 @@ public class ThreadAPI {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetAllStackTraces2() throws Exception {
|
public void testGetAllStackTraces2() throws Exception {
|
||||||
|
if (!ThreadBuilders.supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
try (ForkJoinPool pool = new ForkJoinPool(1)) {
|
try (ForkJoinPool pool = new ForkJoinPool(1)) {
|
||||||
AtomicReference<Thread> ref = new AtomicReference<>();
|
AtomicReference<Thread> ref = new AtomicReference<>();
|
||||||
Executor scheduler = task -> {
|
Executor scheduler = task -> {
|
||||||
@ -2271,7 +2293,6 @@ public class ThreadAPI {
|
|||||||
assertTrue(thread.toString().contains("fred"));
|
assertTrue(thread.toString().contains("fred"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule a thread to be interrupted after a delay.
|
* Schedule a thread to be interrupted after a delay.
|
||||||
*/
|
*/
|
||||||
|
@ -21,32 +21,61 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for creating Thread buidlers.
|
* Helper class for creating Thread buidlers.
|
||||||
|
*
|
||||||
|
* Tests using this class need to open java.base/java.lang.
|
||||||
*/
|
*/
|
||||||
class ThreadBuilders {
|
class ThreadBuilders {
|
||||||
private ThreadBuilders() { }
|
private ThreadBuilders() { }
|
||||||
|
|
||||||
|
private static final Constructor<?> VTBUILDER_CTOR;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
|
||||||
|
Constructor<?> ctor = clazz.getDeclaredConstructor(Executor.class);
|
||||||
|
ctor.setAccessible(true);
|
||||||
|
VTBUILDER_CTOR = ctor;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InternalError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a builder to create virtual threads that use the given scheduler.
|
* Returns a builder to create virtual threads that use the given scheduler.
|
||||||
*
|
* @throws UnsupportedOperationException if custom schedulers are not supported
|
||||||
* Tests using this method need to open java.base/java.lang.
|
|
||||||
*/
|
*/
|
||||||
static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
|
static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
|
||||||
Thread.Builder.OfVirtual builder = Thread.ofVirtual();
|
Thread.Builder.OfVirtual builder = Thread.ofVirtual();
|
||||||
try {
|
try {
|
||||||
Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
|
return (Thread.Builder.OfVirtual) VTBUILDER_CTOR.newInstance(scheduler);
|
||||||
Field field = clazz.getDeclaredField("scheduler");
|
} catch (InvocationTargetException e) {
|
||||||
field.setAccessible(true);
|
Throwable cause = e.getCause();
|
||||||
field.set(builder, scheduler);
|
if (cause instanceof RuntimeException re) {
|
||||||
} catch (RuntimeException | Error e) {
|
throw re;
|
||||||
throw e;
|
}
|
||||||
|
throw new RuntimeException(e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return builder;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if custom schedulers are supported.
|
||||||
|
*/
|
||||||
|
static boolean supportsCustomScheduler() {
|
||||||
|
try (var pool = Executors.newCachedThreadPool()) {
|
||||||
|
try {
|
||||||
|
virtualThreadBuilder(pool);
|
||||||
|
return true;
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Basic test of debugging option to trace pinned threads
|
* @summary Basic test of debugging option to trace pinned threads
|
||||||
|
* @requires vm.continuations
|
||||||
* @compile --enable-preview -source ${jdk.version} TracePinnedThreads.java
|
* @compile --enable-preview -source ${jdk.version} TracePinnedThreads.java
|
||||||
* @run main/othervm --enable-preview -Djdk.tracePinnedThreads=full TracePinnedThreads
|
* @run main/othervm --enable-preview -Djdk.tracePinnedThreads=full TracePinnedThreads
|
||||||
* @run main/othervm --enable-preview -Djdk.tracePinnedThreads=short TracePinnedThreads
|
* @run main/othervm --enable-preview -Djdk.tracePinnedThreads=short TracePinnedThreads
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Stress test asynchronous Thread.getStackTrace
|
* @summary Stress test asynchronous Thread.getStackTrace
|
||||||
* @requires vm.debug != true
|
* @requires vm.debug != true & vm.continuations
|
||||||
* @modules java.base/java.lang:+open
|
* @modules java.base/java.lang:+open
|
||||||
* @compile --enable-preview -source ${jdk.version} GetStackTraceALot.java ../ThreadBuilders.java
|
* @compile --enable-preview -source ${jdk.version} GetStackTraceALot.java ../ThreadBuilders.java
|
||||||
* @run main/othervm --enable-preview GetStackTraceALot
|
* @run main/othervm --enable-preview GetStackTraceALot
|
||||||
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @requires vm.debug == true
|
* @requires vm.debug == true & vm.continuations
|
||||||
* @modules java.base/java.lang:+open
|
* @modules java.base/java.lang:+open
|
||||||
* @compile --enable-preview -source ${jdk.version} GetStackTraceALot.java ../ThreadBuilders.java
|
* @compile --enable-preview -source ${jdk.version} GetStackTraceALot.java ../ThreadBuilders.java
|
||||||
* @run main/othervm/timeout=300 --enable-preview GetStackTraceALot 1000
|
* @run main/othervm/timeout=300 --enable-preview GetStackTraceALot 1000
|
||||||
|
@ -24,13 +24,14 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Stress test virtual threads with a variation of the Skynet 1M benchmark
|
* @summary Stress test virtual threads with a variation of the Skynet 1M benchmark
|
||||||
|
* @requires vm.continuations
|
||||||
* @compile --enable-preview -source ${jdk.version} Skynet.java
|
* @compile --enable-preview -source ${jdk.version} Skynet.java
|
||||||
* @run main/othervm/timeout=300 --enable-preview Skynet
|
* @run main/othervm/timeout=300 --enable-preview Skynet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @requires vm.debug == true
|
* @requires vm.debug == true & vm.continuations
|
||||||
* @requires vm.gc.Z
|
* @requires vm.gc.Z
|
||||||
* @compile --enable-preview -source ${jdk.version} Skynet.java
|
* @compile --enable-preview -source ${jdk.version} Skynet.java
|
||||||
* @run main/othervm/timeout=300 --enable-preview -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm/timeout=300 --enable-preview -XX:+UnlockDiagnosticVMOptions
|
||||||
|
@ -24,14 +24,14 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Stress test Thread.sleep
|
* @summary Stress test Thread.sleep
|
||||||
* @requires vm.debug != true
|
* @requires vm.debug != true & vm.continuations
|
||||||
* @compile --enable-preview -source ${jdk.version} SleepALot.java
|
* @compile --enable-preview -source ${jdk.version} SleepALot.java
|
||||||
* @run main/othervm --enable-preview SleepALot
|
* @run main/othervm --enable-preview SleepALot
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @requires vm.debug == true
|
* @requires vm.debug == true & vm.continuations
|
||||||
* @compile --enable-preview -source ${jdk.version} SleepALot.java
|
* @compile --enable-preview -source ${jdk.version} SleepALot.java
|
||||||
* @run main/othervm/timeout=300 --enable-preview SleepALot 200000
|
* @run main/othervm/timeout=300 --enable-preview SleepALot 200000
|
||||||
*/
|
*/
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Stress parking with CompletableFuture timed get
|
* @summary Stress parking with CompletableFuture timed get
|
||||||
* @requires vm.debug != true
|
* @requires vm.debug != true & vm.continuations
|
||||||
* @compile --enable-preview -source ${jdk.version} TimedGet.java
|
* @compile --enable-preview -source ${jdk.version} TimedGet.java
|
||||||
* @run main/othervm -Xmx1g --enable-preview TimedGet
|
* @run main/othervm -Xmx1g --enable-preview TimedGet
|
||||||
*/
|
*/
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary
|
* @summary
|
||||||
|
* @requires vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @run build TestClass1 TestClass2 TestClass3
|
* @run build TestClass1 TestClass2 TestClass3
|
||||||
* @compile --enable-preview -source ${jdk.version} ParallelTransformerLoaderTest.java
|
* @compile --enable-preview -source ${jdk.version} ParallelTransformerLoaderTest.java
|
||||||
|
@ -26,10 +26,21 @@
|
|||||||
* @bug 8284161 8287103
|
* @bug 8284161 8287103
|
||||||
* @summary Test ThredMXBean.findMonitorDeadlockedThreads with cycles of
|
* @summary Test ThredMXBean.findMonitorDeadlockedThreads with cycles of
|
||||||
* platform and virtual threads in deadlock
|
* platform and virtual threads in deadlock
|
||||||
* @compile --enable-preview -source ${jdk.version} VirtualThreadDeadlocks.java
|
* @enablePreview
|
||||||
* @run main/othervm --enable-preview VirtualThreadDeadlocks PP
|
* @modules java.management
|
||||||
* @run main/othervm --enable-preview VirtualThreadDeadlocks PV
|
* @run main/othervm VirtualThreadDeadlocks PP
|
||||||
* @run main/othervm --enable-preview VirtualThreadDeadlocks VV
|
* @run main/othervm VirtualThreadDeadlocks PV
|
||||||
|
* @run main/othervm VirtualThreadDeadlocks VV
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @requires vm.continuations
|
||||||
|
* @enablePreview
|
||||||
|
* @modules java.management
|
||||||
|
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations VirtualThreadDeadlocks PP
|
||||||
|
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations VirtualThreadDeadlocks PV
|
||||||
|
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations VirtualThreadDeadlocks VV
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
|
@ -23,16 +23,26 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
|
* @bug 8284161
|
||||||
* @summary Test java.lang.management.ThreadMXBean with virtual threads
|
* @summary Test java.lang.management.ThreadMXBean with virtual threads
|
||||||
* @modules java.base/java.lang:+open
|
* @enablePreview
|
||||||
* @compile --enable-preview -source ${jdk.version} VirtualThreads.java
|
* @modules java.base/java.lang:+open java.management
|
||||||
* @run testng/othervm --enable-preview VirtualThreads
|
* @run testng/othervm VirtualThreads
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @requires vm.continuations
|
||||||
|
* @enablePreview
|
||||||
|
* @modules java.base/java.lang:+open java.management
|
||||||
|
* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations VirtualThreads
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.ThreadInfo;
|
import java.lang.management.ThreadInfo;
|
||||||
import java.lang.management.ThreadMXBean;
|
import java.lang.management.ThreadMXBean;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.nio.channels.Selector;
|
import java.nio.channels.Selector;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@ -41,6 +51,7 @@ import java.util.concurrent.Executors;
|
|||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.concurrent.locks.LockSupport;
|
import java.util.concurrent.locks.LockSupport;
|
||||||
|
|
||||||
|
import org.testng.SkipException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
@ -78,6 +89,8 @@ public class VirtualThreads {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetThreadInfo2() throws Exception {
|
public void testGetThreadInfo2() throws Exception {
|
||||||
|
if (!supportsCustomScheduler())
|
||||||
|
throw new SkipException("No support for custom schedulers");
|
||||||
try (ExecutorService pool = Executors.newFixedThreadPool(1)) {
|
try (ExecutorService pool = Executors.newFixedThreadPool(1)) {
|
||||||
var carrierRef = new AtomicReference<Thread>();
|
var carrierRef = new AtomicReference<Thread>();
|
||||||
Executor scheduler = (task) -> {
|
Executor scheduler = (task) -> {
|
||||||
@ -203,18 +216,39 @@ public class VirtualThreads {
|
|||||||
.anyMatch(className::equals);
|
.anyMatch(className::equals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a builder to create virtual threads that use the given scheduler.
|
||||||
|
* @throws UnsupportedOperationException if there is no support for custom schedulers
|
||||||
|
*/
|
||||||
private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
|
private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
|
||||||
Thread.Builder.OfVirtual builder = Thread.ofVirtual();
|
Thread.Builder.OfVirtual builder = Thread.ofVirtual();
|
||||||
try {
|
try {
|
||||||
Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
|
Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
|
||||||
Field field = clazz.getDeclaredField("scheduler");
|
Constructor<?> ctor = clazz.getDeclaredConstructor(Executor.class);
|
||||||
field.setAccessible(true);
|
ctor.setAccessible(true);
|
||||||
field.set(builder, scheduler);
|
return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler);
|
||||||
} catch (RuntimeException | Error e) {
|
} catch (InvocationTargetException e) {
|
||||||
throw e;
|
Throwable cause = e.getCause();
|
||||||
|
if (cause instanceof RuntimeException re) {
|
||||||
|
throw re;
|
||||||
|
}
|
||||||
|
throw new RuntimeException(e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return builder;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if custom schedulers are supported.
|
||||||
|
*/
|
||||||
|
private static boolean supportsCustomScheduler() {
|
||||||
|
try (var pool = Executors.newCachedThreadPool()) {
|
||||||
|
try {
|
||||||
|
virtualThreadBuilder(pool);
|
||||||
|
return true;
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,20 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
|
* @bug 8284161
|
||||||
* @summary Basic tests of virtual threads doing blocking I/O with java.net sockets
|
* @summary Basic tests of virtual threads doing blocking I/O with java.net sockets
|
||||||
|
* @enablePreview
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} BlockingSocketOps.java
|
* @run testng/othervm/timeout=300 BlockingSocketOps
|
||||||
* @run testng/othervm/timeout=300 --enable-preview BlockingSocketOps
|
* @run testng/othervm/timeout=300 -Djdk.useDirectRegister BlockingSocketOps
|
||||||
* @run testng/othervm/timeout=300 --enable-preview -Djdk.useDirectRegister BlockingSocketOps
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @requires vm.continuations
|
||||||
|
* @enablePreview
|
||||||
|
* @library /test/lib
|
||||||
|
* @run testng/othervm/timeout=300 -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations BlockingSocketOps
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
@ -23,11 +23,20 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
|
* @bug 8284161
|
||||||
* @summary Basic tests of virtual threads doing blocking I/O with NIO channels
|
* @summary Basic tests of virtual threads doing blocking I/O with NIO channels
|
||||||
|
* @enablePreview
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} BlockingChannelOps.java
|
* @run testng/othervm/timeout=300 BlockingChannelOps
|
||||||
* @run testng/othervm/timeout=300 --enable-preview BlockingChannelOps
|
* @run testng/othervm/timeout=300 -Djdk.useDirectRegister BlockingChannelOps
|
||||||
* @run testng/othervm/timeout=300 --enable-preview -Djdk.useDirectRegister BlockingChannelOps
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @requires vm.continuations
|
||||||
|
* @enablePreview
|
||||||
|
* @library /test/lib
|
||||||
|
* @run testng/othervm/timeout=300 -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations BlockingChannelOps
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Basic tests for jdk.internal.vm.Continuation
|
* @summary Basic tests for jdk.internal.vm.Continuation
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.base/jdk.internal.vm
|
* @modules java.base/jdk.internal.vm
|
||||||
* @build java.base/java.lang.StackWalkerHelper
|
* @build java.base/java.lang.StackWalkerHelper
|
||||||
*
|
*
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
* @test
|
* @test
|
||||||
* @summary Tests class unloading on virtual threads
|
* @summary Tests class unloading on virtual threads
|
||||||
*
|
*
|
||||||
|
* @requires vm.continuations
|
||||||
* @compile --enable-preview -source ${jdk.version} ClassUnloading.java
|
* @compile --enable-preview -source ${jdk.version} ClassUnloading.java
|
||||||
* @run main/othervm --enable-preview -XX:-UseCompressedOops ClassUnloading
|
* @run main/othervm --enable-preview -XX:-UseCompressedOops ClassUnloading
|
||||||
* @run main/othervm --enable-preview -XX:+UseCompressedOops ClassUnloading
|
* @run main/othervm --enable-preview -XX:+UseCompressedOops ClassUnloading
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
* @test
|
* @test
|
||||||
* @key randomness
|
* @key randomness
|
||||||
* @summary Fuzz tests for jdk.internal.vm.Continuation
|
* @summary Fuzz tests for jdk.internal.vm.Continuation
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.base/jdk.internal.vm
|
* @modules java.base/jdk.internal.vm
|
||||||
*
|
*
|
||||||
* @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
|
* @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Tests humongous stack-chunk handling
|
* @summary Tests humongous stack-chunk handling
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.base/jdk.internal.vm
|
* @modules java.base/jdk.internal.vm
|
||||||
*
|
*
|
||||||
* @requires vm.gc.G1
|
* @requires vm.gc.G1
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Functional test for continuations walked with StackWalker's LiveStackFrames
|
* @summary Functional test for continuations walked with StackWalker's LiveStackFrames
|
||||||
|
* @requires vm.continuations
|
||||||
* @build java.base/java.lang.LiveFrames
|
* @build java.base/java.lang.LiveFrames
|
||||||
* @modules java.base/jdk.internal.vm
|
* @modules java.base/jdk.internal.vm
|
||||||
*
|
*
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Nested continuations test
|
* @summary Nested continuations test
|
||||||
|
* @requires vm.continuations
|
||||||
* @modules java.base/jdk.internal.vm
|
* @modules java.base/jdk.internal.vm
|
||||||
* @build java.base/java.lang.StackWalkerHelper
|
* @build java.base/java.lang.StackWalkerHelper
|
||||||
*
|
*
|
||||||
|
@ -35,7 +35,7 @@ import jdk.test.lib.jfr.Events;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} TestThreadEndEvent.java LatchedThread.java
|
* @compile --enable-preview -source ${jdk.version} TestThreadEndEvent.java LatchedThread.java
|
||||||
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestThreadEndEvent
|
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestThreadEndEvent
|
||||||
|
@ -38,7 +38,7 @@ import jdk.test.lib.jfr.Events;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} TestThreadSleepEvent.java
|
* @compile --enable-preview -source ${jdk.version} TestThreadSleepEvent.java
|
||||||
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestThreadSleepEvent
|
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestThreadSleepEvent
|
||||||
|
@ -35,7 +35,7 @@ import jdk.test.lib.jfr.Events;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} TestThreadStartEvent.java LatchedThread.java
|
* @compile --enable-preview -source ${jdk.version} TestThreadStartEvent.java LatchedThread.java
|
||||||
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestThreadStartEvent
|
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestThreadStartEvent
|
||||||
|
@ -35,7 +35,7 @@ import jdk.test.lib.jfr.Events;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} TestVirtualThreadEndEvent.java LatchedThread.java
|
* @compile --enable-preview -source ${jdk.version} TestVirtualThreadEndEvent.java LatchedThread.java
|
||||||
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestVirtualThreadEndEvent
|
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestVirtualThreadEndEvent
|
||||||
|
@ -35,7 +35,7 @@ import jdk.test.lib.jfr.Events;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile --enable-preview -source ${jdk.version} TestVirtualThreadStartEvent.java LatchedThread.java
|
* @compile --enable-preview -source ${jdk.version} TestVirtualThreadStartEvent.java LatchedThread.java
|
||||||
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestVirtualThreadStartEvent
|
* @run main/othervm --enable-preview jdk.jfr.event.runtime.TestVirtualThreadStartEvent
|
||||||
|
@ -39,7 +39,7 @@ import static jdk.test.lib.Asserts.assertTrue;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @modules jdk.jfr/jdk.jfr.internal
|
* @modules jdk.jfr/jdk.jfr.internal
|
||||||
* @compile --enable-preview -source ${jdk.version} TestThreadExclusion.java LatchedThread.java
|
* @compile --enable-preview -source ${jdk.version} TestThreadExclusion.java LatchedThread.java
|
||||||
|
@ -39,7 +39,7 @@ import static jdk.test.lib.Asserts.assertTrue;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @modules jdk.jfr/jdk.jfr.internal
|
* @modules jdk.jfr/jdk.jfr.internal
|
||||||
* @compile --enable-preview -source ${jdk.version} TestVirtualThreadExclusion.java LatchedThread.java
|
* @compile --enable-preview -source ${jdk.version} TestVirtualThreadExclusion.java LatchedThread.java
|
||||||
|
@ -39,7 +39,7 @@ import jdk.test.lib.jfr.Events;
|
|||||||
* @summary Tests emitting an event, both in Java and native, in a virtual
|
* @summary Tests emitting an event, both in Java and native, in a virtual
|
||||||
* thread with the maximum number of allowed stack frames for JFR
|
* thread with the maximum number of allowed stack frames for JFR
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib /test/jdk
|
* @library /test/lib /test/jdk
|
||||||
* @modules jdk.jfr/jdk.jfr.internal
|
* @modules jdk.jfr/jdk.jfr.internal
|
||||||
* @compile --enable-preview -source ${jdk.version} TestDeepVirtualStackTrace.java
|
* @compile --enable-preview -source ${jdk.version} TestDeepVirtualStackTrace.java
|
||||||
|
@ -40,7 +40,7 @@ import jdk.test.lib.Asserts;
|
|||||||
* @test
|
* @test
|
||||||
* @summary Tests starting virtual threads from a set of ordinary threads
|
* @summary Tests starting virtual threads from a set of ordinary threads
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib /test/jdk
|
* @library /test/lib /test/jdk
|
||||||
* @modules jdk.jfr/jdk.jfr.internal
|
* @modules jdk.jfr/jdk.jfr.internal
|
||||||
* @compile --enable-preview -source ${jdk.version} TestManyVirtualThreads.java
|
* @compile --enable-preview -source ${jdk.version} TestManyVirtualThreads.java
|
||||||
|
@ -38,7 +38,7 @@ import jdk.test.lib.jfr.Events;
|
|||||||
* @summary Tests committing an event in a virtual thread created by a virtual
|
* @summary Tests committing an event in a virtual thread created by a virtual
|
||||||
* thread
|
* thread
|
||||||
* @key jfr
|
* @key jfr
|
||||||
* @requires vm.hasJFR
|
* @requires vm.hasJFR & vm.continuations
|
||||||
* @library /test/lib /test/jdk
|
* @library /test/lib /test/jdk
|
||||||
* @modules jdk.jfr/jdk.jfr.internal
|
* @modules jdk.jfr/jdk.jfr.internal
|
||||||
* @compile --enable-preview -source ${jdk.version} TestNestedVirtualThreads.java
|
* @compile --enable-preview -source ${jdk.version} TestNestedVirtualThreads.java
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -112,6 +112,7 @@ public class VMProps implements Callable<Map<String, String>> {
|
|||||||
map.put("vm.cds", this::vmCDS);
|
map.put("vm.cds", this::vmCDS);
|
||||||
map.put("vm.cds.custom.loaders", this::vmCDSForCustomLoaders);
|
map.put("vm.cds.custom.loaders", this::vmCDSForCustomLoaders);
|
||||||
map.put("vm.cds.write.archived.java.heap", this::vmCDSCanWriteArchivedJavaHeap);
|
map.put("vm.cds.write.archived.java.heap", this::vmCDSCanWriteArchivedJavaHeap);
|
||||||
|
map.put("vm.continuations", this::vmContinuations);
|
||||||
// vm.graal.enabled is true if Graal is used as JIT
|
// vm.graal.enabled is true if Graal is used as JIT
|
||||||
map.put("vm.graal.enabled", this::isGraalEnabled);
|
map.put("vm.graal.enabled", this::isGraalEnabled);
|
||||||
map.put("vm.compiler1.enabled", this::isCompiler1Enabled);
|
map.put("vm.compiler1.enabled", this::isCompiler1Enabled);
|
||||||
@ -421,6 +422,17 @@ public class VMProps implements Callable<Map<String, String>> {
|
|||||||
return "" + ("true".equals(vmCDS()) && WB.canWriteJavaHeapArchive());
|
return "" + ("true".equals(vmCDS()) && WB.canWriteJavaHeapArchive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return "true" if this VM supports continuations.
|
||||||
|
*/
|
||||||
|
protected String vmContinuations() {
|
||||||
|
if (WB.getBooleanVMFlag("VMContinuations")) {
|
||||||
|
return "true";
|
||||||
|
} else {
|
||||||
|
return "false";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return System page size in bytes.
|
* @return System page size in bytes.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user