|
Java example source code file (hprof_event.c)
The hprof_event.c Java example source code/* * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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 Oracle 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. */ /* * This source code is provided to illustrate the usage of a given feature * or technique and has been deliberately simplified. Additional steps * required for a production-quality application, such as security checks, * input validation and proper error handling, might not be present in * this sample code. */ /* This file contains all class, method and allocation event support functions, * both JVMTI and BCI events. * (See hprof_monitor.c for the monitor event handlers). */ #include "hprof.h" /* Private internal functions. */ /* Return a TraceIndex for the given thread. */ static TraceIndex get_current(TlsIndex tls_index, JNIEnv *env, jboolean skip_init) { TraceIndex trace_index; trace_index = tls_get_trace(tls_index, env, gdata->max_trace_depth, skip_init); return trace_index; } /* Return a ClassIndex for the given jclass, loader supplied or looked up. */ static ClassIndex find_cnum(JNIEnv *env, jclass klass, jobject loader) { LoaderIndex loader_index; ClassIndex cnum; char * signature; HPROF_ASSERT(klass!=NULL); /* Get the loader index */ loader_index = loader_find_or_create(env, loader); /* Get the signature for this class */ getClassSignature(klass, &signature, NULL); /* Find the ClassIndex for this class */ cnum = class_find_or_create(signature, loader_index); /* Free the signature space */ jvmtiDeallocate(signature); /* Make sure we save a global reference to this class in the table */ HPROF_ASSERT(cnum!=0); (void)class_new_classref(env, cnum, klass); return cnum; } /* Get the ClassIndex for the superClass of this jclass. */ static ClassIndex get_super(JNIEnv *env, jclass klass) { ClassIndex super_cnum; super_cnum = 0; WITH_LOCAL_REFS(env, 1) { jclass super_klass; super_klass = getSuperclass(env, klass); if ( super_klass != NULL ) { super_cnum = find_cnum(env, super_klass, getClassLoader(super_klass)); } } END_WITH_LOCAL_REFS; return super_cnum; } /* Record an allocation. Could be jobject, jclass, jarray or primitive type. */ static void any_allocation(JNIEnv *env, SerialNumber thread_serial_num, TraceIndex trace_index, jobject object) { SiteIndex site_index; ClassIndex cnum; jint size; jclass klass; /* NOTE: Normally the getObjectClass() and getClassLoader() * would require a * WITH_LOCAL_REFS(env, 1) { * } END_WITH_LOCAL_REFS; * but for performance reasons we skip it here. */ /* Get and tag the klass */ klass = getObjectClass(env, object); cnum = find_cnum(env, klass, getClassLoader(klass)); site_index = site_find_or_create(cnum, trace_index); tag_class(env, klass, cnum, thread_serial_num, site_index); /* Tag the object */ size = (jint)getObjectSize(object); tag_new_object(object, OBJECT_NORMAL, thread_serial_num, size, site_index); } /* Handle a java.lang.Object.<init> object allocation. */ void event_object_init(JNIEnv *env, jthread thread, jobject object) { /* Called via BCI Tracker class */ /* Be very careful what is called here, watch out for recursion. */ jint *pstatus; TraceIndex trace_index; SerialNumber thread_serial_num; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); HPROF_ASSERT(object!=NULL); /* Prevent recursion into any BCI function for this thread (pstatus). */ if ( tls_get_tracker_status(env, thread, JNI_TRUE, &pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) { (*pstatus) = 1; any_allocation(env, thread_serial_num, trace_index, object); (*pstatus) = 0; } } /* Handle any newarray opcode allocation. */ void event_newarray(JNIEnv *env, jthread thread, jobject object) { /* Called via BCI Tracker class */ /* Be very careful what is called here, watch out for recursion. */ jint *pstatus; TraceIndex trace_index; SerialNumber thread_serial_num; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); HPROF_ASSERT(object!=NULL); /* Prevent recursion into any BCI function for this thread (pstatus). */ if ( tls_get_tracker_status(env, thread, JNI_FALSE, &pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) { (*pstatus) = 1; any_allocation(env, thread_serial_num, trace_index, object); (*pstatus) = 0; } } /* Handle tracking of a method call. */ void event_call(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) { /* Called via BCI Tracker class */ /* Be very careful what is called here, watch out for recursion. */ TlsIndex tls_index; jint *pstatus; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); if (cnum == 0 || cnum == gdata->tracker_cnum) { jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); (*env)->ThrowNew(env, newExcCls, "Illegal cnum."); return; } /* Prevent recursion into any BCI function for this thread (pstatus). */ if ( tls_get_tracker_status(env, thread, JNI_FALSE, &pstatus, &tls_index, NULL, NULL) == 0 ) { jmethodID method; (*pstatus) = 1; method = class_get_methodID(env, cnum, mnum); if (method != NULL) { tls_push_method(tls_index, method); } (*pstatus) = 0; } } /* Handle tracking of an exception catch */ void event_exception_catch(JNIEnv *env, jthread thread, jmethodID method, jlocation location, jobject exception) { /* Called via JVMTI_EVENT_EXCEPTION_CATCH callback */ /* Be very careful what is called here, watch out for recursion. */ TlsIndex tls_index; jint *pstatus; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); HPROF_ASSERT(method!=NULL); /* Prevent recursion into any BCI function for this thread (pstatus). */ if ( tls_get_tracker_status(env, thread, JNI_FALSE, &pstatus, &tls_index, NULL, NULL) == 0 ) { (*pstatus) = 1; tls_pop_exception_catch(tls_index, thread, method); (*pstatus) = 0; } } /* Handle tracking of a method return pop one (maybe more) methods. */ void event_return(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) { /* Called via BCI Tracker class */ /* Be very careful what is called here, watch out for recursion. */ TlsIndex tls_index; jint *pstatus; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); if (cnum == 0 || cnum == gdata->tracker_cnum) { jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); (*env)->ThrowNew(env, newExcCls, "Illegal cnum."); return; } /* Prevent recursion into any BCI function for this thread (pstatus). */ if ( tls_get_tracker_status(env, thread, JNI_FALSE, &pstatus, &tls_index, NULL, NULL) == 0 ) { jmethodID method; (*pstatus) = 1; method = class_get_methodID(env, cnum, mnum); if (method != NULL) { tls_pop_method(tls_index, thread, method); } (*pstatus) = 0; } } /* Handle a class prepare (should have been already loaded) */ void event_class_prepare(JNIEnv *env, jthread thread, jclass klass, jobject loader) { /* Called via JVMTI_EVENT_CLASS_PREPARE event */ ClassIndex cnum; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); HPROF_ASSERT(klass!=NULL); /* Find the ClassIndex for this class */ cnum = find_cnum(env, klass, loader); class_add_status(cnum, CLASS_PREPARED); } /* Handle a class load (could have been already loaded) */ void event_class_load(JNIEnv *env, jthread thread, jclass klass, jobject loader) { /* Called via JVMTI_EVENT_CLASS_LOAD event or reset_class_load_status() */ ClassIndex cnum; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(klass!=NULL); /* Find the ClassIndex for this class */ cnum = find_cnum(env, klass, loader); /* Always mark it as being in the load list */ class_add_status(cnum, CLASS_IN_LOAD_LIST); /* If we are seeing this as a new loaded class, extra work */ if ( ! ( class_get_status(cnum) & CLASS_LOADED ) ) { TraceIndex trace_index; SiteIndex site_index; ClassIndex super; SerialNumber class_serial_num; SerialNumber trace_serial_num; SerialNumber thread_serial_num; ObjectIndex class_object_index; char *signature; /* Get the TlsIndex and a TraceIndex for this location */ if ( thread == NULL ) { /* This should be very rare, but if this class load was simulated * from hprof_init.c due to a reset of the class load status, * and it originated from a pre-VM_INIT event, the jthread * would be NULL, or it was a jclass created that didn't get * reported to us, like an array class or a primitive class? */ trace_index = gdata->system_trace_index; thread_serial_num = gdata->unknown_thread_serial_num; } else { TlsIndex tls_index; tls_index = tls_find_or_create(env, thread); trace_index = get_current(tls_index, env, JNI_FALSE); thread_serial_num = tls_get_thread_serial_number(tls_index); } /* Get the SiteIndex for this location and a java.lang.Class object */ /* Note that the target cnum, not the cnum for java.lang.Class. */ site_index = site_find_or_create(cnum, trace_index); /* Tag this java.lang.Class object */ tag_class(env, klass, cnum, thread_serial_num, site_index); class_add_status(cnum, CLASS_LOADED); class_serial_num = class_get_serial_number(cnum); class_object_index = class_get_object_index(cnum); trace_serial_num = trace_get_serial_number(trace_index); signature = string_get(class_get_signature(cnum)); rawMonitorEnter(gdata->data_access_lock); { io_write_class_load(class_serial_num, class_object_index, trace_serial_num, signature); } rawMonitorExit(gdata->data_access_lock); super = get_super(env, klass); class_set_super(cnum, super); } } /* Handle a thread start event */ void event_thread_start(JNIEnv *env, jthread thread) { /* Called via JVMTI_EVENT_THREAD_START event */ TlsIndex tls_index; ObjectIndex object_index; TraceIndex trace_index; jlong tag; SerialNumber thread_serial_num; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); tls_index = tls_find_or_create(env, thread); thread_serial_num = tls_get_thread_serial_number(tls_index); trace_index = get_current(tls_index, env, JNI_FALSE); tag = getTag(thread); if ( tag == (jlong)0 ) { SiteIndex site_index; jint size; size = (jint)getObjectSize(thread); site_index = site_find_or_create(gdata->thread_cnum, trace_index); /* We create a new object with this thread's serial number */ object_index = object_new(site_index, size, OBJECT_NORMAL, thread_serial_num); } else { object_index = tag_extract(tag); /* Normally the Thread object is created and tagged before we get * here, but the thread_serial_number on this object isn't what * we want. So we update it to the serial number of this thread. */ object_set_thread_serial_number(object_index, thread_serial_num); } tls_set_thread_object_index(tls_index, object_index); WITH_LOCAL_REFS(env, 1) { jvmtiThreadInfo threadInfo; jvmtiThreadGroupInfo threadGroupInfo; jvmtiThreadGroupInfo parentGroupInfo; getThreadInfo(thread, &threadInfo); getThreadGroupInfo(threadInfo.thread_group, &threadGroupInfo); if ( threadGroupInfo.parent != NULL ) { getThreadGroupInfo(threadGroupInfo.parent, &parentGroupInfo); } else { (void)memset(&parentGroupInfo, 0, sizeof(parentGroupInfo)); } rawMonitorEnter(gdata->data_access_lock); { io_write_thread_start(thread_serial_num, object_index, trace_get_serial_number(trace_index), threadInfo.name, threadGroupInfo.name, parentGroupInfo.name); } rawMonitorExit(gdata->data_access_lock); jvmtiDeallocate(threadInfo.name); jvmtiDeallocate(threadGroupInfo.name); jvmtiDeallocate(parentGroupInfo.name); } END_WITH_LOCAL_REFS; } void event_thread_end(JNIEnv *env, jthread thread) { /* Called via JVMTI_EVENT_THREAD_END event */ TlsIndex tls_index; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); tls_index = tls_find_or_create(env, thread); rawMonitorEnter(gdata->data_access_lock); { io_write_thread_end(tls_get_thread_serial_number(tls_index)); } rawMonitorExit(gdata->data_access_lock); tls_thread_ended(env, tls_index); setThreadLocalStorage(thread, (void*)NULL); } Other Java examples (source code examples)Here is a short list of links related to this Java hprof_event.c source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.