Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8284028

[LOOM] JVMTI is confused about current thread when JNI FindClass intercept is called

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Cannot Reproduce
    • Affects Version/s: repo-loom
    • Fix Version/s: 19
    • Component/s: hotspot
    • Labels:

      Description

      JVMTI provides a mechanism for intercepting JNI calls. For example, to intercept FindClass calls, you can do the following:

      jvmti->GetJNIFunctionTable(&redir_jni_functions);
      redir_jni_functions->FindClass = MyFindClass;
      jvmti->SetJNIFunctionTable(redir_jni_functions);

      I noticed in a couple of JVMTI tests, there is some confusion over the current thread when the intercept call is made. If the current thread is a virtual thread, for some reason GetThreadInfo(NULL) returns the name of the carrier thread, even though GetStackTrace(NULL) properly returns the stack trace of the virtual thread. This can be observed in the FindClass callback in the following test:

         vmTestbase/nsk/jvmti/scenarios/jni_interception/JI01/ji01t001/

      If you add the following to the MyFindClass method:

          nsk_printf("MyFindClass(%s)\n",classname);

          jvmtiThreadInfo threadinfo;
          NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(NULL, &threadinfo));
          nsk_printf("thread name: %s\n", threadinfo.name);

          jvmtiError err;
          jvmtiFrameInfo f[30];
          jclass callerClass;
          char *sigClass, *name, *sig, *generic;
          jint i, count;
          err = jvmti->GetStackTrace(NULL, 0, 30, f, &count);
          for (i = 0; i < count; i++) {
              jvmti->GetMethodDeclaringClass(f[i].method, &callerClass);
              jvmti->GetClassSignature(callerClass, &sigClass, &generic);
              jvmti->GetMethodName(f[i].method, &name, &sig, &generic);
              nsk_printf(">>> frame %d: %s %s%s\n", i, sigClass, name, sig);
          }

      And run with:

      make test TEST=open/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/jni_interception/JI01/ji01t001/ JTREG_MAIN_WRAPPER=Virtual

      You will see the following in the output:

      MyFindClass(Lnsk/jvmti/scenarios/jni_interception/JI01/ji01t001;)
      thread name: ForkJoinPool-1-worker-1
      >>> frame 0: Ljava/lang/Shutdown; halt0(I)V
      >>> frame 1: Ljava/lang/Shutdown; halt(I)V
      >>> frame 2: Ljava/lang/Shutdown; exit(I)V
      >>> frame 3: Ljava/lang/Runtime; exit(I)V
      >>> frame 4: Ljava/lang/System; exit(I)V
      >>> frame 5: Lnsk/jvmti/scenarios/jni_interception/JI01/ji01t001; main([Ljava/lang/String;)V
      >>> frame 6: Ljava/lang/invoke/LambdaForm$DMH.0x0000000801003c00; invokeStatic(Ljava/lang/Object;Ljava/lang/Object;)V
      >>> frame 7: Ljava/lang/invoke/LambdaForm$MH.0x0000000801004c00; invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      >>> frame 8: Ljava/lang/invoke/Invokers$Holder; invokeExact_MT(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      >>> frame 9: Ljdk/internal/reflect/DirectMethodHandleAccessor; invokeImpl(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
      >>> frame 10: Ljdk/internal/reflect/DirectMethodHandleAccessor; invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
      >>> frame 11: Ljava/lang/reflect/Method; invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
      >>> frame 12: Lcom/sun/javatest/regtest/agent/MainWrapper$MainTask; run()V
      >>> frame 13: Ljava/lang/VirtualThread; run(Ljava/lang/Runnable;)V
      >>> frame 14: Ljava/lang/VirtualThread$VThreadContinuation; lambda$new$0(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V
      >>> frame 15: Ljava/lang/VirtualThread$VThreadContinuation$$Lambda$6.0x000000080104b170; run()V
      >>> frame 16: Ljdk/internal/vm/Continuation; enter0()V
      >>> frame 17: Ljdk/internal/vm/Continuation; enter(Ljdk/internal/vm/Continuation;Z)V

      Notice the following:
      - classname is for a class the test is trying to load
      - the thread name is for a carrier thread
      - the thread stack trace is for a virtual thread
      - we are in the middle of a VM shutdown.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              sspitsyn Serguei Spitsyn
              Reporter:
              cjplummer Chris Plummer
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: