--- /dev/null Thu Jan 7 14:58:24 2010 +++ new/jdk/src/share/demo/jvmti/compiledMethodLoad/compiledMethodLoad.c Thu Jan 7 14:58:24 2010 @@ -0,0 +1,268 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "jni.h" +#include "jvmti.h" +#include "jvmticmlr.h" + +#include "agent_util.h" + +/* Global static data */ +static char OUTPUT_FILE[] = "compiledMethodLoad.txt"; +static FILE *fp; +static jvmtiEnv *jvmti; +static jrawMonitorID lock; + +/* print a jvmtiCompiledMethodLoadDummyRecord */ +void +print_dummy_record(jvmtiCompiledMethodLoadDummyRecord* record, + jvmtiEnv* jvmti, FILE* fp) { + + if (record != NULL) { + fprintf(fp, "Dummy record detected containing message: %s\n", + (char *)record->message); + } +} + +/* print the specified stack frames */ +void +print_stack_frames(PCStackInfo* record, jvmtiEnv *jvmti, FILE* fp) { + if (record != NULL && record->methods != NULL) { + int i; + + for (i = 0; i < record->numstackframes; i++) { + jvmtiError err; + char* method_name = NULL; + char* class_name = NULL; + char* method_signature = NULL; + char* class_signature = NULL; + char* generic_ptr_method = NULL; + char* generic_ptr_class = NULL; + jmethodID id; + jclass declaringclassptr; + id = record->methods[i]; + + err = (*jvmti)->GetMethodDeclaringClass(jvmti, id, + &declaringclassptr); + check_jvmti_error(jvmti, err, "get method declaring class"); + + err = (*jvmti)->GetClassSignature(jvmti, declaringclassptr, + &class_signature, &generic_ptr_class); + check_jvmti_error(jvmti, err, "get class signature"); + + err = (*jvmti)->GetMethodName(jvmti, id, &method_name, + &method_signature, &generic_ptr_method); + check_jvmti_error(jvmti, err, "get method name"); + + fprintf(fp, "%s::%s %s %s @%d\n", class_signature, method_name, + method_signature, + generic_ptr_method == NULL ? "" : generic_ptr_method, + record->bcis[i]); + + if (method_name != NULL) { + err = (*jvmti)->Deallocate(jvmti, (unsigned char*)method_name); + check_jvmti_error(jvmti, err, "deallocate method_name"); + } + if (method_signature != NULL) { + err = (*jvmti)->Deallocate(jvmti, + (unsigned char*)method_signature); + check_jvmti_error(jvmti, err, "deallocate method_signature"); + } + if (generic_ptr_method != NULL) { + err = (*jvmti)->Deallocate(jvmti, + (unsigned char*)generic_ptr_method); + check_jvmti_error(jvmti, err, "deallocate generic_ptr_method"); + } + if (class_name != NULL) { + err = (*jvmti)->Deallocate(jvmti, (unsigned char*)class_name); + check_jvmti_error(jvmti, err, "deallocate class_name"); + } + if (class_signature != NULL) { + err = (*jvmti)->Deallocate(jvmti, + (unsigned char*)class_signature); + check_jvmti_error(jvmti, err, "deallocate class_signature"); + } + if (generic_ptr_class != NULL) { + err = (*jvmti)->Deallocate(jvmti, + (unsigned char*)generic_ptr_class); + check_jvmti_error(jvmti, err, "deallocate generic_ptr_class"); + } + } + } +} + +/* print a jvmtiCompiledMethodLoadInlineRecord */ +void +print_inline_info_record(jvmtiCompiledMethodLoadInlineRecord* record, + jvmtiEnv *jvmti, FILE* fp) { + + if (record != NULL && record->pcinfo != NULL) { + int numpcs = record->numpcs; + int i; + + for (i = 0; i < numpcs; i++) { + PCStackInfo pcrecord = (record->pcinfo[i]); + fprintf(fp, "PcDescriptor(pc=0x%lx):\n", (jint)(pcrecord.pc)); + print_stack_frames(&pcrecord, jvmti, fp); + } + } +} + +/* decode kind of CompiledMethodLoadRecord and print */ +void +print_records(jvmtiCompiledMethodLoadRecordHeader* list, jvmtiEnv *jvmti, + FILE* fp) +{ + jvmtiCompiledMethodLoadRecordHeader* curr = list; + fprintf(fp, "\nPrinting PC Descriptors\n\n"); + while (curr != NULL) { + switch (curr->kind) { + case JVMTI_CMLR_DUMMY: + print_dummy_record((jvmtiCompiledMethodLoadDummyRecord *)curr, + jvmti, fp); + break; + + case JVMTI_CMLR_INLINE_INFO: + print_inline_info_record( + (jvmtiCompiledMethodLoadInlineRecord *)curr, jvmti, fp); + break; + + default: + fprintf(fp, "Warning: unrecognized record: kind=%d\n", curr->kind); + break; + } + + curr = (jvmtiCompiledMethodLoadRecordHeader *)curr->next; + } +} + +/* Callback for JVMTI_EVENT_COMPILED_METHOD_LOAD */ +void JNICALL +compiled_method_load(jvmtiEnv *jvmti, jmethodID method, jint code_size, + const void* code_addr, jint map_length, const jvmtiAddrLocationMap* map, + const void* compile_info) +{ + jvmtiError err; + char* name = NULL; + char* signature = NULL; + char* generic_ptr = NULL; + jvmtiCompiledMethodLoadRecordHeader* pcs; + + err = (*jvmti)->RawMonitorEnter(jvmti, lock); + check_jvmti_error(jvmti, err, "raw monitor enter"); + + err = (*jvmti)->GetMethodName(jvmti, method, &name, &signature, + &generic_ptr); + check_jvmti_error(jvmti, err, "get method name"); + + fprintf(fp, "\nCompiled method load event\n"); + fprintf(fp, "Method name %s %s %s\n\n", name, signature, + generic_ptr == NULL ? "" : generic_ptr); + pcs = (jvmtiCompiledMethodLoadRecordHeader *)compile_info; + if (pcs != NULL) { + print_records(pcs, jvmti, fp); + } + + if (name != NULL) { + err = (*jvmti)->Deallocate(jvmti, (unsigned char*)name); + check_jvmti_error(jvmti, err, "deallocate name"); + } + if (signature != NULL) { + err = (*jvmti)->Deallocate(jvmti, (unsigned char*)signature); + check_jvmti_error(jvmti, err, "deallocate signature"); + } + if (generic_ptr != NULL) { + err = (*jvmti)->Deallocate(jvmti, (unsigned char*)generic_ptr); + check_jvmti_error(jvmti, err, "deallocate generic_ptr"); + } + + err = (*jvmti)->RawMonitorExit(jvmti, lock); + check_jvmti_error(jvmti, err, "raw monitor exit"); +} + +/* Agent_OnLoad() is called first, we prepare for a COMPILED_METHOD_LOAD + * event here. + */ +JNIEXPORT jint JNICALL +Agent_OnLoad(JavaVM *vm, char *options, void *reserved) +{ + jint rc; + jvmtiError err; + jvmtiCapabilities capabilities; + jvmtiEventCallbacks callbacks; + + fp = fopen(OUTPUT_FILE, "w"); + if (fp == NULL) { + fatal_error("ERROR: %s: Unable to create output file\n", OUTPUT_FILE); + return -1; + } + + /* Get JVMTI environment */ + rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION); + if (rc != JNI_OK) { + fatal_error( + "ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc); + return -1; + } + + /* add JVMTI capabilities */ + memset(&capabilities,0, sizeof(capabilities)); + capabilities.can_generate_compiled_method_load_events = 1; + err = (*jvmti)->AddCapabilities(jvmti, &capabilities); + check_jvmti_error(jvmti, err, "add capabilities"); + + /* set JVMTI callbacks for events */ + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.CompiledMethodLoad = &compiled_method_load; + err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks)); + check_jvmti_error(jvmti, err, "set event callbacks"); + + /* enable JVMTI events */ + err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL); + check_jvmti_error(jvmti, err, "set event notify"); + + /* create coordination monitor */ + err = (*jvmti)->CreateRawMonitor(jvmti, "agent lock", &lock); + check_jvmti_error(jvmti, err, "create raw monitor"); + + return 0; +} + +/* Agent_OnUnload() is called last */ +JNIEXPORT void JNICALL +Agent_OnUnload(JavaVM *vm) +{ +}