1 Reply Latest reply: Oct 27, 2012 2:16 AM by 971002 RSS

    Agent_OnLoad, VMInit / Death never called.

    971002
      Hello all,

      First of all, my environment details:-

      OS: Windows 7 64 bit
      JDK: 1.7

      Now, I have a very simple JVMTI agent which prints messages on screen in the OnLoad, OnUnload, VMInit, VMDeath events. My agent runs fine with the following Java program:-
      public class Main {
           
           public static void main(String[] args) {
                System.out.println("Executed");
                     
           }
      }
      The above when executed prints the following:-

      Executed+
      Agent Onload+
      VM INIT+
      VM DEATH+
      Agent OnUnload+

      However, it prints nothing at all if I run the following Java code:-
      public class Main {
           
           public static void main(String[] args) {
                System.out.println("Executed");
                new Thread(new Worker()).start();     
           }
           
           private static class Worker implements Runnable {
      
                @Override
                public void run() {
                     while(true) {
                          try {
                               Thread.sleep(500);
                               //System.out.println("Testing");
                          } catch(Exception e) {
                          }
                     }
                }
           }
      }
      It only prints out the string Executed*

      Notice that in the second case, I have a perpetually running Java program. However, shouldn't the Agent_OnLoad and the vmInit methods not be called at the very least here as well? Am I missing something here? Please find the agent code below:-
      #include <jni.h>
      #include <jni_md.h>
      #include <jvmti.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <stddef.h>
      #include <string.h>
      
      
      
      jvmtiEnv *env = NULL;
      jrawMonitorID lock;
      
      void enterAgentMonitor() {
           env->RawMonitorEnter(lock);
      }
      
      void exitAgentMonitor() {
           env->RawMonitorExit(lock);
      }
      
      
      static void JNICALL vmInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) {
           enterAgentMonitor(); 
           {
                fprintf(stdout, "VM INIT\n");    
           } 
           exitAgentMonitor();
      }
      
      
      static void JNICALL vmDeath(jvmtiEnv *jvmti, JNIEnv *env) {
           jvmtiError err;
           err = jvmti->ForceGarbageCollection();
           enterAgentMonitor(); 
           {
                fprintf(stdout, "VM DEATH\n");
           } 
           exitAgentMonitor();
      }
      
      JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
           fprintf(stdout, "Agent Onload\n");
           
           jvm->GetEnv((void **)&env, JVMTI_VERSION);
      
           //Create the lock used for critical sections within the agent.
           env->CreateRawMonitor("Lock", &lock);
      
           jvmtiCapabilities jvmCaps;
           jvmtiEventCallbacks callbacks;
           memset(&jvmCaps, 0, sizeof(jvmtiCapabilities));
           memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
      
           //Add the capabilities that we will need for method callbacks.
           jvmCaps.can_signal_thread = 1;
           jvmCaps.can_get_owned_monitor_info = 1;
           jvmCaps.can_generate_method_entry_events = 1;
           jvmCaps.can_generate_exception_events = 1;
           jvmCaps.can_generate_vm_object_alloc_events = 1;
           jvmCaps.can_tag_objects = 1;
           env->AddCapabilities(&jvmCaps);
      
           callbacks.VMInit = &vmInit;
           callbacks.VMDeath = &vmDeath;
           
           env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, 0);
           env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, 0);
      
           env->SetEventCallbacks(&callbacks, sizeof(jvmtiEventCallbacks));
      
           return JNI_OK;
      }
      
      JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
           fprintf(stdout, "Agent OnUnload\n");
      }
      The VM correctly points to the DLL using the agentpath VM argument in both the cases. Any help will be appreciated!

      Edited by: 967999 on Oct 27, 2012 12:08 AM

      Edited by: 967999 on Oct 27, 2012 12:11 AM