@@ -32,14 +32,15 @@ int VM::_hotspot_version = 0;
3232bool VM::_openj9 = false ;
3333bool VM::_zing = false ;
3434
35+ GetCreatedJavaVMs VM::_getCreatedJavaVMs = NULL ;
36+
3537jvmtiError (JNICALL *VM::_orig_RedefineClasses)(jvmtiEnv*, jint, const jvmtiClassDefinition*);
3638jvmtiError (JNICALL *VM::_orig_RetransformClasses)(jvmtiEnv*, jint, const jclass* classes);
3739
3840AsyncGetCallTrace VM::_asyncGetCallTrace;
3941JVM_MemoryFunc VM::_totalMemory;
4042JVM_MemoryFunc VM::_freeMemory;
4143
42-
4344static bool isVmRuntimeEntry (const char * blob_name) {
4445 return strcmp (blob_name, " _ZNK12MemAllocator8allocateEv" ) == 0
4546 || strncmp (blob_name, " _Z22post_allocation_notify" , 26 ) == 0
@@ -106,6 +107,30 @@ static void* resolveMethodIdEnd() {
106107 return NULL ;
107108}
108109
110+ // Workaround for JDK-8308341: since JNI_GetCreatedJavaVMs may return an uninitialized JVM,
111+ // we verify the readiness of the JVM by presence of "VM Thread" and "Service Thread".
112+ bool VM::hasJvmThreads () {
113+ char thread_name[32 ];
114+ int threads_found = 0 ;
115+
116+ ThreadList* list = OS::listThreads ();
117+ while (list->hasNext () && threads_found != 3 ) {
118+ if (!OS::threadName (list->next (), thread_name, sizeof (thread_name))) {
119+ continue ;
120+ }
121+
122+ // On macOS, Java thread names start with "Java: "
123+ int thread_name_offset = strncmp (thread_name, " Java: " , 6 ) == 0 ? 6 : 0 ;
124+
125+ if (strcmp (thread_name + thread_name_offset, " VM Thread" ) == 0 ) {
126+ threads_found |= 1 ;
127+ } else if (strcmp (thread_name + thread_name_offset, " Service Thread" ) == 0 ) {
128+ threads_found |= 2 ;
129+ }
130+ }
131+
132+ return threads_found == 3 ;
133+ }
109134
110135bool VM::init (JavaVM* vm, bool attach) {
111136 if (_jvmti != NULL ) return true ;
@@ -275,6 +300,38 @@ bool VM::init(JavaVM* vm, bool attach) {
275300 return true ;
276301}
277302
303+ // Try to find a running JVM instance and attach to it
304+ void VM::tryAttach () {
305+ if (_getCreatedJavaVMs == NULL ) {
306+ void * lib_handle = dlopen (OS::isLinux () ? " libjvm.so" : " libjvm.dylib" , RTLD_LAZY | RTLD_NOLOAD);
307+ if (lib_handle != NULL ) {
308+ _getCreatedJavaVMs = (GetCreatedJavaVMs)dlsym (lib_handle, " JNI_GetCreatedJavaVMs" );
309+ dlclose (lib_handle);
310+ }
311+ if (_getCreatedJavaVMs == NULL ) {
312+ return ;
313+ }
314+ }
315+
316+ JavaVM* vm;
317+ jsize nVMs;
318+ if (_getCreatedJavaVMs (&vm, 1 , &nVMs) != JNI_OK || nVMs != 1 ) {
319+ return ;
320+ }
321+
322+ JNIEnv* env;
323+ jint get_env_result = vm->GetEnv ((void **)&env, JNI_VERSION_1_6);
324+ if (get_env_result == JNI_OK) {
325+ // Current thread already belongs to the running JVM
326+ VM::init (vm, true );
327+ } else if (get_env_result == JNI_EDETACHED) {
328+ // There is a running JVM, but we need to check it is initialized
329+ if (hasJvmThreads () && vm->AttachCurrentThreadAsDaemon ((void **)&env, NULL ) == JNI_OK) {
330+ VM::init (vm, true );
331+ }
332+ }
333+ }
334+
278335// Run late initialization when JVM is ready
279336void VM::ready () {
280337 Profiler::setupSignalHandlers ();
0 commit comments