Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_event.c
38829 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940/* This file contains all class, method and allocation event support functions,41* both JVMTI and BCI events.42* (See hprof_monitor.c for the monitor event handlers).43*/4445#include "hprof.h"4647/* Private internal functions. */4849/* Return a TraceIndex for the given thread. */50static TraceIndex51get_current(TlsIndex tls_index, JNIEnv *env, jboolean skip_init)52{53TraceIndex trace_index;5455trace_index = tls_get_trace(tls_index, env, gdata->max_trace_depth, skip_init);56return trace_index;57}5859/* Return a ClassIndex for the given jclass, loader supplied or looked up. */60static ClassIndex61find_cnum(JNIEnv *env, jclass klass, jobject loader)62{63LoaderIndex loader_index;64ClassIndex cnum;65char * signature;6667HPROF_ASSERT(klass!=NULL);6869/* Get the loader index */70loader_index = loader_find_or_create(env, loader);7172/* Get the signature for this class */73getClassSignature(klass, &signature, NULL);7475/* Find the ClassIndex for this class */76cnum = class_find_or_create(signature, loader_index);7778/* Free the signature space */79jvmtiDeallocate(signature);8081/* Make sure we save a global reference to this class in the table */82HPROF_ASSERT(cnum!=0);83(void)class_new_classref(env, cnum, klass);84return cnum;85}8687/* Get the ClassIndex for the superClass of this jclass. */88static ClassIndex89get_super(JNIEnv *env, jclass klass)90{91ClassIndex super_cnum;9293super_cnum = 0;94WITH_LOCAL_REFS(env, 1) {95jclass super_klass;9697super_klass = getSuperclass(env, klass);98if ( super_klass != NULL ) {99super_cnum = find_cnum(env, super_klass,100getClassLoader(super_klass));101}102} END_WITH_LOCAL_REFS;103return super_cnum;104}105106/* Record an allocation. Could be jobject, jclass, jarray or primitive type. */107static void108any_allocation(JNIEnv *env, SerialNumber thread_serial_num,109TraceIndex trace_index, jobject object)110{111SiteIndex site_index;112ClassIndex cnum;113jint size;114jclass klass;115116/* NOTE: Normally the getObjectClass() and getClassLoader()117* would require a118* WITH_LOCAL_REFS(env, 1) {119* } END_WITH_LOCAL_REFS;120* but for performance reasons we skip it here.121*/122123/* Get and tag the klass */124klass = getObjectClass(env, object);125cnum = find_cnum(env, klass, getClassLoader(klass));126site_index = site_find_or_create(cnum, trace_index);127tag_class(env, klass, cnum, thread_serial_num, site_index);128129/* Tag the object */130size = (jint)getObjectSize(object);131tag_new_object(object, OBJECT_NORMAL, thread_serial_num, size, site_index);132}133134/* Handle a java.lang.Object.<init> object allocation. */135void136event_object_init(JNIEnv *env, jthread thread, jobject object)137{138/* Called via BCI Tracker class */139140/* Be very careful what is called here, watch out for recursion. */141142jint *pstatus;143TraceIndex trace_index;144SerialNumber thread_serial_num;145146HPROF_ASSERT(env!=NULL);147HPROF_ASSERT(thread!=NULL);148HPROF_ASSERT(object!=NULL);149150/* Prevent recursion into any BCI function for this thread (pstatus). */151if ( tls_get_tracker_status(env, thread, JNI_TRUE,152&pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) {153(*pstatus) = 1;154any_allocation(env, thread_serial_num, trace_index, object);155(*pstatus) = 0;156}157}158159/* Handle any newarray opcode allocation. */160void161event_newarray(JNIEnv *env, jthread thread, jobject object)162{163/* Called via BCI Tracker class */164165/* Be very careful what is called here, watch out for recursion. */166167jint *pstatus;168TraceIndex trace_index;169SerialNumber thread_serial_num;170171HPROF_ASSERT(env!=NULL);172HPROF_ASSERT(thread!=NULL);173HPROF_ASSERT(object!=NULL);174175/* Prevent recursion into any BCI function for this thread (pstatus). */176if ( tls_get_tracker_status(env, thread, JNI_FALSE,177&pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) {178(*pstatus) = 1;179any_allocation(env, thread_serial_num, trace_index, object);180(*pstatus) = 0;181}182}183184/* Handle tracking of a method call. */185void186event_call(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum)187{188/* Called via BCI Tracker class */189190/* Be very careful what is called here, watch out for recursion. */191192TlsIndex tls_index;193jint *pstatus;194195HPROF_ASSERT(env!=NULL);196HPROF_ASSERT(thread!=NULL);197if (cnum == 0 || cnum == gdata->tracker_cnum) {198jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");199if ((*env)->ExceptionCheck(env)) {200(*env)->ExceptionClear(env);201HPROF_ERROR(JNI_TRUE,202"Could not find the java/lang/IllegalArgumentException class");203}204(*env)->ThrowNew(env, newExcCls, "Illegal cnum.");205206return;207}208209/* Prevent recursion into any BCI function for this thread (pstatus). */210if ( tls_get_tracker_status(env, thread, JNI_FALSE,211&pstatus, &tls_index, NULL, NULL) == 0 ) {212jmethodID method;213214(*pstatus) = 1;215method = class_get_methodID(env, cnum, mnum);216if (method != NULL) {217tls_push_method(tls_index, method);218}219220(*pstatus) = 0;221}222}223224/* Handle tracking of an exception catch */225void226event_exception_catch(JNIEnv *env, jthread thread, jmethodID method,227jlocation location, jobject exception)228{229/* Called via JVMTI_EVENT_EXCEPTION_CATCH callback */230231/* Be very careful what is called here, watch out for recursion. */232233TlsIndex tls_index;234jint *pstatus;235236HPROF_ASSERT(env!=NULL);237HPROF_ASSERT(thread!=NULL);238HPROF_ASSERT(method!=NULL);239240/* Prevent recursion into any BCI function for this thread (pstatus). */241if ( tls_get_tracker_status(env, thread, JNI_FALSE,242&pstatus, &tls_index, NULL, NULL) == 0 ) {243(*pstatus) = 1;244tls_pop_exception_catch(tls_index, thread, method);245(*pstatus) = 0;246}247}248249/* Handle tracking of a method return pop one (maybe more) methods. */250void251event_return(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum)252{253/* Called via BCI Tracker class */254255/* Be very careful what is called here, watch out for recursion. */256257TlsIndex tls_index;258jint *pstatus;259260HPROF_ASSERT(env!=NULL);261HPROF_ASSERT(thread!=NULL);262263if (cnum == 0 || cnum == gdata->tracker_cnum) {264jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");265if ((*env)->ExceptionCheck(env)) {266(*env)->ExceptionClear(env);267HPROF_ERROR(JNI_TRUE,268"Could not find the java/lang/IllegalArgumentException class");269}270(*env)->ThrowNew(env, newExcCls, "Illegal cnum.");271272return;273}274275/* Prevent recursion into any BCI function for this thread (pstatus). */276if ( tls_get_tracker_status(env, thread, JNI_FALSE,277&pstatus, &tls_index, NULL, NULL) == 0 ) {278jmethodID method;279280(*pstatus) = 1;281method = class_get_methodID(env, cnum, mnum);282if (method != NULL) {283tls_pop_method(tls_index, thread, method);284}285286(*pstatus) = 0;287}288}289290/* Handle a class prepare (should have been already loaded) */291void292event_class_prepare(JNIEnv *env, jthread thread, jclass klass, jobject loader)293{294/* Called via JVMTI_EVENT_CLASS_PREPARE event */295296ClassIndex cnum;297298HPROF_ASSERT(env!=NULL);299HPROF_ASSERT(thread!=NULL);300HPROF_ASSERT(klass!=NULL);301302/* Find the ClassIndex for this class */303cnum = find_cnum(env, klass, loader);304class_add_status(cnum, CLASS_PREPARED);305306}307308/* Handle a class load (could have been already loaded) */309void310event_class_load(JNIEnv *env, jthread thread, jclass klass, jobject loader)311{312/* Called via JVMTI_EVENT_CLASS_LOAD event or reset_class_load_status() */313314ClassIndex cnum;315316HPROF_ASSERT(env!=NULL);317HPROF_ASSERT(klass!=NULL);318319/* Find the ClassIndex for this class */320cnum = find_cnum(env, klass, loader);321322/* Always mark it as being in the load list */323class_add_status(cnum, CLASS_IN_LOAD_LIST);324325/* If we are seeing this as a new loaded class, extra work */326if ( ! ( class_get_status(cnum) & CLASS_LOADED ) ) {327TraceIndex trace_index;328SiteIndex site_index;329ClassIndex super;330SerialNumber class_serial_num;331SerialNumber trace_serial_num;332SerialNumber thread_serial_num;333ObjectIndex class_object_index;334char *signature;335336/* Get the TlsIndex and a TraceIndex for this location */337if ( thread == NULL ) {338/* This should be very rare, but if this class load was simulated339* from hprof_init.c due to a reset of the class load status,340* and it originated from a pre-VM_INIT event, the jthread341* would be NULL, or it was a jclass created that didn't get342* reported to us, like an array class or a primitive class?343*/344trace_index = gdata->system_trace_index;345thread_serial_num = gdata->unknown_thread_serial_num;346} else {347TlsIndex tls_index;348349tls_index = tls_find_or_create(env, thread);350trace_index = get_current(tls_index, env, JNI_FALSE);351thread_serial_num = tls_get_thread_serial_number(tls_index);352}353354/* Get the SiteIndex for this location and a java.lang.Class object */355/* Note that the target cnum, not the cnum for java.lang.Class. */356site_index = site_find_or_create(cnum, trace_index);357358/* Tag this java.lang.Class object */359tag_class(env, klass, cnum, thread_serial_num, site_index);360361class_add_status(cnum, CLASS_LOADED);362363class_serial_num = class_get_serial_number(cnum);364class_object_index = class_get_object_index(cnum);365trace_serial_num = trace_get_serial_number(trace_index);366signature = string_get(class_get_signature(cnum));367368rawMonitorEnter(gdata->data_access_lock); {369io_write_class_load(class_serial_num, class_object_index,370trace_serial_num, signature);371} rawMonitorExit(gdata->data_access_lock);372373super = get_super(env, klass);374class_set_super(cnum, super);375}376377}378379/* Handle a thread start event */380void381event_thread_start(JNIEnv *env, jthread thread)382{383/* Called via JVMTI_EVENT_THREAD_START event */384385TlsIndex tls_index;386ObjectIndex object_index;387TraceIndex trace_index;388jlong tag;389SerialNumber thread_serial_num;390391HPROF_ASSERT(env!=NULL);392HPROF_ASSERT(thread!=NULL);393394tls_index = tls_find_or_create(env, thread);395thread_serial_num = tls_get_thread_serial_number(tls_index);396trace_index = get_current(tls_index, env, JNI_FALSE);397398tag = getTag(thread);399if ( tag == (jlong)0 ) {400SiteIndex site_index;401jint size;402403size = (jint)getObjectSize(thread);404site_index = site_find_or_create(gdata->thread_cnum, trace_index);405/* We create a new object with this thread's serial number */406object_index = object_new(site_index, size, OBJECT_NORMAL,407thread_serial_num);408} else {409object_index = tag_extract(tag);410/* Normally the Thread object is created and tagged before we get411* here, but the thread_serial_number on this object isn't what412* we want. So we update it to the serial number of this thread.413*/414object_set_thread_serial_number(object_index, thread_serial_num);415}416tls_set_thread_object_index(tls_index, object_index);417418WITH_LOCAL_REFS(env, 1) {419jvmtiThreadInfo threadInfo;420jvmtiThreadGroupInfo threadGroupInfo;421jvmtiThreadGroupInfo parentGroupInfo;422423getThreadInfo(thread, &threadInfo);424getThreadGroupInfo(threadInfo.thread_group, &threadGroupInfo);425if ( threadGroupInfo.parent != NULL ) {426getThreadGroupInfo(threadGroupInfo.parent, &parentGroupInfo);427} else {428(void)memset(&parentGroupInfo, 0, sizeof(parentGroupInfo));429}430431rawMonitorEnter(gdata->data_access_lock); {432io_write_thread_start(thread_serial_num,433object_index, trace_get_serial_number(trace_index),434threadInfo.name, threadGroupInfo.name, parentGroupInfo.name);435} rawMonitorExit(gdata->data_access_lock);436437jvmtiDeallocate(threadInfo.name);438jvmtiDeallocate(threadGroupInfo.name);439jvmtiDeallocate(parentGroupInfo.name);440441} END_WITH_LOCAL_REFS;442}443444void445event_thread_end(JNIEnv *env, jthread thread)446{447/* Called via JVMTI_EVENT_THREAD_END event */448TlsIndex tls_index;449450HPROF_ASSERT(env!=NULL);451HPROF_ASSERT(thread!=NULL);452453tls_index = tls_find_or_create(env, thread);454rawMonitorEnter(gdata->data_access_lock); {455io_write_thread_end(tls_get_thread_serial_number(tls_index));456} rawMonitorExit(gdata->data_access_lock);457tls_thread_ended(env, tls_index);458setThreadLocalStorage(thread, (void*)NULL);459}460461462