From: Jens W. <jen...@de...> - 2007-05-11 17:48:32
|
This patch contains the example JVMTI implementation. Don't know whether the destination exta/jvmti is a good idea and whether we need to add this on "make install" also. extra/jvmti/Makefile | 18 +++++ extra/jvmti/README | 30 +++++++++ extra/jvmti/jvmti_oprofile.c | 140 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+) --- oprofile-0.9.2/extra/jvmti/jvmti_oprofile.c 1970-01-01 01:00:00.000000000 +0100 +++ oprofile-jitadaptions/extra/jvmti/jvmti_oprofile.c 2007-05-11 11:01:06.000000000 +0200 @@ -0,0 +1,140 @@ +/** + * @file jvmti_oprofile.c + * JVMTI agent implementation to report jitted JVM code to Oprofile + * + * @remark Copyright 2007 OProfile authors + * @remark Read the file COPYING + * + * @author Jens Wilke + * + * Copyright IBM Corporation 2007 + * + */ + +#include <stdio.h> +#include <jvmti.h> +#include <string.h> +#include <libopagent.h> + +void JNICALL +cbCompiledMethodLoad(jvmtiEnv *jvmti, + jmethodID method, + jint code_size, + const void* code_addr, + jint map_length, + const jvmtiAddrLocationMap* map, + const void* compile_info) +{ + /* Get the declaring class of the method */ + jclass declaringClass; + char * classSig = NULL; + char * methodName = NULL; + char * methodSig = NULL; + jvmtiError err; + + err = (*jvmti)->GetMethodDeclaringClass(jvmti, method, &declaringClass); + if (err != JVMTI_ERROR_NONE) { + fprintf(stderr, "Error, GetMethodDeclaringClass, rc=%i\n", err); + goto cleanup; + } + err = (*jvmti)->GetClassSignature(jvmti, declaringClass, &classSig, NULL); + if (err != JVMTI_ERROR_NONE) { + fprintf(stderr, "Error, GetClassSignature, rc=%i\n", err); + goto cleanup; + } + err = (*jvmti)->GetMethodName(jvmti, method, &methodName, &methodSig, NULL); + if (err != JVMTI_ERROR_NONE) { + fprintf(stderr, "Error, GeMethodName, rc=%i\n", err); + goto cleanup; + } + + /* DEBUG + fprintf(stderr, "class=%s, methodName=%s, methodSig=%s, addr=%x, size=%i \n", classSig, methodName, methodSig, code_addr, code_size); + */ + { + int cnt = strlen(methodName)+strlen(classSig)+2; + char buf[cnt]; + + /* cut away the ; */ + classSig[strlen(classSig)-1] = 0; + sprintf(buf, "%s/%s", classSig+1, methodName); + op_write_native_code(buf, code_addr, code_size); + } + + + cleanup: + if (classSig!=NULL) { (*jvmti)->Deallocate (jvmti, classSig); } + if (methodName!=NULL) { (*jvmti)->Deallocate (jvmti, methodName); } + if (methodSig!=NULL) { (*jvmti)->Deallocate (jvmti, methodSig); } +} + +void JNICALL cbCompiledMethodUnload (jvmtiEnv *jvmti_env, jmethodID method, + const void* code_addr) +{ +} + +void JNICALL cbDynamicCodeGenerated (jvmtiEnv *jvmti_env, const char* name, + const void* code_addr, jint code_size) +{ +} + +JNIEXPORT jint JNICALL +Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) +{ + jint rc; + jvmtiEnv *jvmti = NULL; + jvmtiEventCallbacks callbacks; + jvmtiCapabilities caps; + jvmtiError error; + int err; + + fprintf(stderr, "jvmti_oprofile: agent loading\n"); + err = op_open_agent(); + if (err) { + fprintf(stderr, "ERROR: op_open_agent, rc=%i\n", err); + return -1; + } + + /* Get the jvmti environment */ + rc = (*jvm)->GetEnv(jvm, (void **) &jvmti, JVMTI_VERSION_1); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: Unable to access JVMTI Version 1, rc=%i\n", rc); + return -1; + } + rc = (*jvmti)->GetCapabilities(jvmti, &caps); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: GetCapabilities, rc=%i\n", rc); + return -1; + } + caps.can_generate_compiled_method_load_events = 1; + rc = (*jvmti)->AddCapabilities(jvmti, &caps); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: AddCapabilities, rc=%i\n", rc); + return -1; + } + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.CompiledMethodLoad = cbCompiledMethodLoad; + callbacks.CompiledMethodUnload = cbCompiledMethodUnload; + callbacks.DynamicCodeGenerated = cbDynamicCodeGenerated; + rc = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks)); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: SetEventCallbacks, rc=%i\n", rc); + return -1; + } + + rc = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_COMPILED_METHOD_LOAD, (jthread)NULL); + rc = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_COMPILED_METHOD_UNLOAD, (jthread)NULL); + rc = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_DYNAMIC_CODE_GENERATED, (jthread)NULL); + fprintf(stderr, "jvmti_oprofile: initialized, producing output of jitted methods\n"); + + return 0; +} + +JNIEXPORT void JNICALL +Agent_OnUnload(JavaVM *vm) +{ + op_close_agent(); +} --- oprofile-0.9.2/extra/jvmti/README 1970-01-01 01:00:00.000000000 +0100 +++ oprofile-jitadaptions/extra/jvmti/README 2007-05-11 10:20:19.000000000 +0200 @@ -0,0 +1,30 @@ +What is this? +------------- + +This is an JVMTI agent implementation that works with JDKs 1.5 or +higher. It retrieves names and assembly code of jitted methods +of the JVM, for later display in an Oprofile report. + +Installation +------------ + +Edit the directory of your JDK and Oprofile installation in +the Makefile and run make. + +There is no make install target, however, it makes sense to +keep the created lib libjvmti_oprofile.so together with +the JDK that it was compiled for. + +Usage +----- + +Start the JDK with the extra parameter: + +-agentpath:<installdir>/libjvmti_oprofile.so + +The modified Oprofile can be used as before. For short running +java workloads the buffer watershed must be reduced, because +the Oprofile daemon retrieves additional information from the process +when the buffer is processed. E.g. start the sampling with the parameters: + +opcontrol --start --buffer-size=131072 --buffer-watershed=131000 --- oprofile-0.9.2/extra/jvmti/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ oprofile-jitadaptions/extra/jvmti/Makefile 2007-05-11 10:03:14.000000000 +0200 @@ -0,0 +1,18 @@ +# replace this to fit your installation +JDK=${JAVA_HOME} +OPROFILE=/opt/oprofile-exp + +OPAGENTLIB=$(OPROFILE)/lib +OPLIBFLAGS=-lopagent -L$(OPAGENTLIB) + +# for the sun jdk we need the addition os include -I$(JDK)/include/linux +# see http://java.sun.com/products/jdk/faq/jni-j2sdk-faq.html#jni_md +INCLUDES=-I$(OPROFILE)/include -I$(JDK)/include -I$(JDK)/include/linux + +all: libjvmti_oprofile.so + +clean: + rm libjvmti_oprofile.so + +libjvmti_oprofile.so: jvmti_oprofile.c Makefile + gcc -shared -o $@ -Wl,-soname=$@ -static-libgcc -lc $(INCLUDES) $(OPLIBFLAGS) $< |