4 Replies Latest reply on Oct 2, 2008 6:50 AM by 843810

    Could not find agent library on the library path or in the local directory

    843810
      Hi all,
      I'm trying to write a jvmti agent that write any information in a mysql db. I've written a simple agent that work correctly and now I'll try to insert the mysqlpp library in my agent:
      1) I've added #include <mysql++.h>
      2) and I've added mysqlpp::Connection      conn(false); (global variable)

      I've modify my Makefile and the compiler and linker work correctly but when I test the agent the VM says "Could not find agent library on the library path or in the local directory"

      Below the code:
      -- analizer.cpp --
      #include <iostream>
      #include <stdlib.h>
      #include <jni.h>
      #include <string.h>
      #include <jvmti.h>
      #include <mysql++.h>
      #include "ClassDetail.cpp"
      
      
      #define CFN(ptr) checkForNull(ptr, __FILE__, __LINE__);
      static void checkForNull(void *ptr, const char* file, int line) {
          if(ptr == NULL) {
              std::cerr << "ERROR : NullPointerException in " << file <<":"<< line<<"\n";
              abort();
          }
      }
      
      static char* getErrorName(jvmtiEnv *jvmti, jvmtiError err) {
          jvmtiError errNum;
          char *name;
          errNum = jvmti->GetErrorName(err, &name);
          if( errNum != JVMTI_ERROR_NONE) {
              std::cerr << "ERROR : errore nel reprire l'error name " << errNum;
              abort();
          }
          return name;
      }
      #define CJVMTIE(jvmti, err) checkJvmtiError(jvmti, err, __FILE__, __LINE__);
      static void checkJvmtiError(jvmtiEnv *jvmti, jvmtiError err, const char* file, int line) {
          if(err != JVMTI_ERROR_NONE) {
              char *name = getErrorName(jvmti, err);
              std::cout << "ERROR : JVMTI error " << err << "("<<name<<") in "<<file<<":"<<line;
              abort();
          }
      }
      
      static void vmInit(jvmtiEnv *jvmti_env, JNIEnv *jni, jthread thread);
      static void startGCEvent(jvmtiEnv *jvmti_env);
      static void finishGCEvent(jvmtiEnv *jvmti_env);
      static jvmtiIterationControl JNICALL heapObject(jlong tag, jlong size, jlong* tag_ptr, void* userData);
      jrawMonitorID           lock;
      int                     gc_count;
      long                    heapSize = 0;
      bool                    heapCheck = false;
      
      mysqlpp::Connection      conn(false);
      
      
      JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
          std::cout<<"OnLoad\n";
          jint                rc;
          jvmtiEnv            *jvmti = NULL;
          jvmtiError          err;
          jvmtiCapabilities   capabilities;
          jvmtiEventCallbacks callbacks;
      
          rc = vm->GetEnv((void **)&jvmti, JVMTI_VERSION);
          if( rc != JNI_OK) {
              std::cout << "ERROR : Errore nell'ottenere 'environment rc = " << rc;
              return -1;
          }
          CFN(jvmti);
          err = jvmti->GetCapabilities(&capabilities);
          CJVMTIE(jvmti, err);
          CFN(&capabilities);
          capabilities.can_generate_garbage_collection_events = true;
          capabilities.can_tag_objects = true;
          CJVMTIE(jvmti, jvmti->AddCapabilities(&capabilities));
          CJVMTIE(jvmti, jvmti->CreateRawMonitor("agent lock", &lock));
          callbacks.VMInit = &vmInit;
          callbacks.GarbageCollectionStart = &startGCEvent;
          callbacks.GarbageCollectionFinish = &finishGCEvent;
          CJVMTIE(jvmti, jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)));
          jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
          jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_START, NULL);
          jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL);
      
          return 0;
      }
      
      JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)
      {
          std::cout<<"OnUnload\n";
      }
      
      static void JNICALL worker(jvmtiEnv *jvmti, JNIEnv *jni, void *p) {
          std::cout << "worker";
          for (;;) {
              CJVMTIE(jvmti, jvmti->RawMonitorEnter(lock));
              while (gc_count == 0) {
                  CJVMTIE(jvmti, jvmti->RawMonitorWait(lock, 0));
                  jvmti->RawMonitorExit(lock);
              }
              gc_count = 0;
      
              jvmti->RawMonitorExit(lock);
      
              /* Perform arbitrary JVMTI/JNI work here to do post-GC cleanup */
              if(!heapCheck) {
                  heapCheck = true;
                  jint        count;
                  jclass    *classes;
                  CJVMTIE(jvmti, jvmti->GetLoadedClasses(&count, &classes));
                  ClassDetail *details = (ClassDetail*)calloc(sizeof(ClassDetail), count);
                  for(int i = 0; i < count; i++) {
                      char *sig;
                      CJVMTIE(jvmti, jvmti->GetClassSignature(classes, &sig, NULL));
      CFN(sig);
      details[i] = ClassDetail(strdup(sig));
      CJVMTIE(jvmti, jvmti->SetTag(classes[i], (jlong)(ptrdiff_t)(void*) (&details[i])));
      }
      heapSize = 0;
      CJVMTIE(jvmti, jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_EITHER, &heapObject, NULL));
      std::cout << "Heap Memory : " << heapSize<<'\n';
      heapCheck = false;
      }
      }
      }

      static void vmInit(jvmtiEnv jvmti, JNIEnv jni, jthread thread) {
      jclass clazz = jni->FindClass("java/lang/Thread");
      jmethodID mid = jni->GetMethodID(clazz, "<init>", "()V");
      jthread _thread = jni->NewObject(clazz, mid);

      CJVMTIE(jvmti, jvmti->RunAgentThread(_thread, &worker, NULL, JVMTI_THREAD_MAX_PRIORITY));
      }

      static void startGCEvent(jvmtiEnv *jvmti) {
      }
      static void finishGCEvent(jvmtiEnv *jvmti) {
      std::cout << "****************************************************************** <<<<<<<<<<<< Finito gc\n";
      gc_count++;
      CJVMTIE(jvmti,jvmti->RawMonitorEnter(lock));
      CJVMTIE(jvmti,jvmti->RawMonitorNotify(lock));
      CJVMTIE(jvmti,jvmti->RawMonitorExit(lock));
      }


      static jvmtiIterationControl JNICALL heapObject(jlong tag, jlong size, jlong* tag_ptr, void* userData) {
      /*
      if(tag != (jlong) 0) {
      std::cout << "Tag : " << tag<< '\n';
      ClassDetail detail = (ClassDetail) (void*) (ptrdiff_t) tag;
      char *sig = detail->getSignature();

      std::cout << "Class " << sig << " size : " << size<<'\n';
      }
      */
      heapSize += size;
      return JVMTI_ITERATION_CONTINUE;
      }
      -- ClassDetail.cpp --
      class ClassDetail {
      private:
      char* signature;
      public:
      ClassDetail(char* signature){
      this->signature = signature;
      }

      char* getSignature() { return this->signature;}


      };
      --Makefile--
      ########################################################################
      #
      # Sample GNU Makefile for building JVMTI Demo waiters
      #
      # Example uses:
      # gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
      # gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
      # gnumake JDK=<java_home> OSNAME=linux [OPT=true]
      # gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
      #
      ########################################################################

      # Source lists
      LIBNAME=analizer
      SOURCES=analizer.cpp

      MYSQLPP_LIB_PATH=/home/claudio/Desktop/Scaricati2/mysql++-3.0.6/mysqlpp_lib/lib/
      MYSQLPP_HEADER_PATH=/home/claudio/Desktop/Scaricati2/mysql++-3.0.6/mysqlpp_lib/include/mysql++
      MYSQL_PATH=/opt/mysql-5.0.51a-linux-i686-icc-glibc23


      # Solaris Sun C Compiler Version 5.5
      ifeq ($(OSNAME), solaris)
      # Tell gnumake which compilers to use
      CC=cc
      CXX=CC
      # Sun Solaris Compiler options needed
      COMMON_FLAGS=-mt -KPIC
      # Check LIBARCH for any special compiler options
      LIBARCH=$(shell uname -p)
      ifeq ($(LIBARCH), sparc)
      COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
      endif
      ifeq ($(LIBARCH), sparcv9)
      COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
      endif
      ifeq ($(OPT), true)
      CXXFLAGS=-xO2 $(COMMON_FLAGS)
      else
      CXXFLAGS=-g $(COMMON_FLAGS)
      endif
      # Object files needed to create library
      OBJECTS=$(SOURCES:%.cpp=%.o)
      # Library name and options needed to build it
      LIBRARY=lib$(LIBNAME).so
      LDFLAGS=-z defs -ztext
      # Libraries we are dependent on
      LIBRARIES= -lc
      # Building a shared library
      LINK_SHARED=$(LINK.cc) -G -o $@
      endif

      # Linux GNU C Compiler
      ifeq ($(OSNAME), linux)
      # GNU Compiler options needed to build it
      COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
      # Options that help find errors
      COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
      ifeq ($(OPT), true)
      CXXFLAGS=-O2 $(COMMON_FLAGS)
      else
      CXXFLAGS=-g $(COMMON_FLAGS)
      endif
      # Object files needed to create library
      OBJECTS=$(SOURCES:%.cpp=%.o)
      # Library name and options needed to build it
      LIBRARY=lib$(LIBNAME).so
      LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc -mimpure-text
      LDFLAGS += -lmysqlpp
      # Libraries we are dependent on
      LIBRARIES=
      # Building a shared library
      LINK_SHARED=$(LINK.cc) -shared -o $@
      endif

      # Windows Microsoft C/C++ Optimizing Compiler Version 12
      ifeq ($(OSNAME), win32)
      CC=cl
      # Compiler options needed to build it
      COMMON_FLAGS=-Gy -DWIN32
      # Options that help find errors
      COMMON_FLAGS+=-W0 -WX
      ifeq ($(OPT), true)
      CXXFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
      else
      CXXFLAGS= -Od -Zi $(COMMON_FLAGS)
      endif
      # Object files needed to create library
      OBJECTS=$(SOURCES:%.cpp=%.obj)
      # Library name and options needed to build it
      LIBRARY=$(LIBNAME).dll
      LDFLAGS=
      # Libraries we are dependent on
      LIBRARIES=
      # Building a shared library
      LINK_SHARED=link -dll -out:$@
      endif

      # Common -I options
      CXXFLAGS += -I.
      #CXXFLAGS += -I../agent_util
      CXXFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)

      CXXFLAGS += -I$(MYSQLPP_HEADER_PATH) -I$(MYSQL_PATH)/include -L$(MYSQLPP_LIB_PATH) -I$(MYSQLPP_LIB_PATH)


      # Default rule
      all: $(LIBRARY)

      # Build native library
      $(LIBRARY): $(OBJECTS)
           $(LINK_SHARED) $(OBJECTS) $(LIBRARIES)

      # Cleanup the built bits
      clean:
           rm -f $(LIBRARY) $(OBJECTS)

      # Simple tester
      test: all
           LD_LIBRARY_PATH=`pwd` $(JDK)/bin/java -agentlib:$(LIBNAME) -jar jvmti-test.jar
           #LD_LIBRARY_PATH=`pwd` $(JDK)/bin/java -agentlib:$(LIBNAME) -version

      # Compilation rule only needed on Windows
      ifeq ($(OSNAME), win32)
      %.obj: %.cpp
           $(COMPILE.cc) $<
      endif