diff -r a7e698aed0b7 -r 125cdb60b55f jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.c --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.c Thu Aug 20 11:38:18 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,320 +0,0 @@ -/* - * Copyright (c) 2003, 2011, 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. - */ - - -/* Tracker class support functions. */ - -/* - * This file contains the native support calls for the Tracker - * class. These native methods are registered and not made extern. - * Tracking is engaged by using JNI to assign to a static field in the - * Tracker class. - * - * Just like JVMTI callbacks, it's best that we keep track of these so that - * when the VM_DEATH happens we know to wait for them to complete. - * - * This file also contains the functions that will initialize the Tracker - * interface for BCI and identify the Tracker methods to make sure - * they are not included in any stack traces obtained from JVMTI. - * - * RFE: The performance of the java injected code calling native methods - * could be an issue here, cpu=times seems to be the worst where - * a native call is made for entry and exit, even on the smallest - * Java method. The alternative would be to cache the data on - * the Java side, and either push it out to the native side, or - * use some kind of pull from the native side, or even using - * shared memory or a socket. However having said that, the - * current performance issues are more around sheer memory needed, - * and repeated calls to GetThreadCpuTime(), which is being investigated. - * - */ - -#include "hprof.h" - -/* Macros to surround tracker based callback code. - * Also see BEGIN_CALLBACK and END_CALLBACK in hprof_init.c. - * If the VM_DEATH callback is active in the begining, then this callback - * just blocks (it is assumed we don't want to return to the VM). - * If the VM_DEATH callback is active at the end, then this callback - * will notify the VM_DEATH callback if it's the last one. - * - * WARNING: No not 'return' or 'goto' out of the BEGIN_TRACKER_CALLBACK/END_TRACKER_CALLBACK - * block, this will mess up the count. - */ - -#define BEGIN_TRACKER_CALLBACK() \ -{ /* BEGIN OF TRACKER_CALLBACK */ \ - jboolean bypass = JNI_TRUE; \ - rawMonitorEnter(gdata->callbackLock); { \ - if ( gdata->tracking_engaged != 0 ) { \ - if (!gdata->vm_death_callback_active) { \ - gdata->active_callbacks++; \ - bypass = JNI_FALSE; \ - } \ - } \ - } rawMonitorExit(gdata->callbackLock); \ - if ( !bypass ) { \ - /* BODY OF TRACKER_CALLBACK CODE */ - -#define END_TRACKER_CALLBACK() /* Part of bypass if body */ \ - rawMonitorEnter(gdata->callbackLock); { \ - gdata->active_callbacks--; \ - if (gdata->active_callbacks < 0) { \ - HPROF_ERROR(JNI_TRUE, "Problems tracking callbacks"); \ - } \ - if (gdata->vm_death_callback_active) { \ - if (gdata->active_callbacks == 0) { \ - rawMonitorNotifyAll(gdata->callbackLock); \ - } \ - } \ - } rawMonitorExit(gdata->callbackLock); \ - } \ -} /* END OF TRACKER_CALLBACK */ - - -/* - * Class: Tracker - * Method: nativeNewArray - * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V - */ -static void JNICALL -Tracker_nativeNewArray - (JNIEnv *env, jclass clazz, jobject thread, jobject obj) -{ - BEGIN_TRACKER_CALLBACK() { - event_newarray(env, thread, obj); - } END_TRACKER_CALLBACK(); -} - -/* - * Class: Tracker - * Method: nativeObjectInit - * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V - */ -static void JNICALL -Tracker_nativeObjectInit - (JNIEnv *env, jclass clazz, jobject thread, jobject obj) -{ - BEGIN_TRACKER_CALLBACK() { - event_object_init(env, thread, obj); - } END_TRACKER_CALLBACK(); -} - -/* - * Class: Tracker - * Method: nativeCallSite - * Signature: (Ljava/lang/Object;II)V - */ -static void JNICALL -Tracker_nativeCallSite - (JNIEnv *env, jclass clazz, jobject thread, jint cnum, jint mnum) -{ - BEGIN_TRACKER_CALLBACK() { - event_call(env, thread, cnum, mnum); - } END_TRACKER_CALLBACK(); -} - -/* - * Class: Tracker - * Method: nativeReturnSite - * Signature: (Ljava/lang/Object;II)V - */ -static void JNICALL -Tracker_nativeReturnSite - (JNIEnv *env, jclass clazz, jobject thread, jint cnum, jint mnum) -{ - BEGIN_TRACKER_CALLBACK() { - event_return(env, thread, cnum, mnum); - } END_TRACKER_CALLBACK(); -} - - -/* ------------------------------------------------------------------- */ -/* Set Java static field to turn on native code calls in Tracker. */ - -static void -set_engaged(JNIEnv *env, jint engaged) -{ - LOG3("set_engaged()", "engaging tracking", engaged); - - if ( ! gdata->bci ) { - return; - } - rawMonitorEnter(gdata->callbackLock); { - if ( gdata->tracking_engaged != engaged ) { - jfieldID field; - jclass tracker_class; - - tracker_class = class_get_class(env, gdata->tracker_cnum); - gdata->tracking_engaged = 0; - /* Activate or deactivate the injection code on the Java side */ - HPROF_ASSERT(tracker_class!=NULL); - exceptionClear(env); - field = getStaticFieldID(env, tracker_class, - TRACKER_ENGAGED_NAME, TRACKER_ENGAGED_SIG); - setStaticIntField(env, tracker_class, field, engaged); - exceptionClear(env); - - LOG3("set_engaged()", "tracking engaged", engaged); - - gdata->tracking_engaged = engaged; - } - } rawMonitorExit(gdata->callbackLock); -} - -void -tracker_engage(JNIEnv *env) -{ - set_engaged(env, 0xFFFF); -} - -void -tracker_disengage(JNIEnv *env) -{ - set_engaged(env, 0); -} - -jboolean -tracker_method(jmethodID method) -{ - int i; - - if ( ! gdata->bci ) { - return JNI_FALSE; - } - - HPROF_ASSERT(method!=NULL); - HPROF_ASSERT(gdata->tracker_method_count > 0); - for ( i = 0 ; i < gdata->tracker_method_count ; i++ ) { - HPROF_ASSERT(gdata->tracker_methods[i].method!=NULL); - if ( method == gdata->tracker_methods[i].method ) { - return JNI_TRUE; - } - } - return JNI_FALSE; -} - -static JNINativeMethod registry[4] = -{ - { TRACKER_NEWARRAY_NATIVE_NAME, TRACKER_NEWARRAY_NATIVE_SIG, - (void*)&Tracker_nativeNewArray }, - { TRACKER_OBJECT_INIT_NATIVE_NAME, TRACKER_OBJECT_INIT_NATIVE_SIG, - (void*)&Tracker_nativeObjectInit }, - { TRACKER_CALL_NATIVE_NAME, TRACKER_CALL_NATIVE_SIG, - (void*)&Tracker_nativeCallSite }, - { TRACKER_RETURN_NATIVE_NAME, TRACKER_RETURN_NATIVE_SIG, - (void*)&Tracker_nativeReturnSite } -}; - -static struct { - char *name; - char *sig; -} tracker_methods[] = - { - { TRACKER_NEWARRAY_NAME, TRACKER_NEWARRAY_SIG }, - { TRACKER_OBJECT_INIT_NAME, TRACKER_OBJECT_INIT_SIG }, - { TRACKER_CALL_NAME, TRACKER_CALL_SIG }, - { TRACKER_RETURN_NAME, TRACKER_RETURN_SIG }, - { TRACKER_NEWARRAY_NATIVE_NAME, TRACKER_NEWARRAY_NATIVE_SIG }, - { TRACKER_OBJECT_INIT_NATIVE_NAME, TRACKER_OBJECT_INIT_NATIVE_SIG }, - { TRACKER_CALL_NATIVE_NAME, TRACKER_CALL_NATIVE_SIG }, - { TRACKER_RETURN_NATIVE_NAME, TRACKER_RETURN_NATIVE_SIG } - }; - -void -tracker_setup_class(void) -{ - ClassIndex cnum; - LoaderIndex loader_index; - - HPROF_ASSERT(gdata->tracker_cnum==0); - loader_index = loader_find_or_create(NULL,NULL); - cnum = class_find_or_create(TRACKER_CLASS_SIG, loader_index); - gdata->tracker_cnum = cnum; - HPROF_ASSERT(cnum!=0); - class_add_status(cnum, CLASS_SPECIAL); -} - -void -tracker_setup_methods(JNIEnv *env) -{ - ClassIndex cnum; - LoaderIndex loader_index; - int i; - jclass object_class; - jclass tracker_class; - - if ( ! gdata->bci ) { - return; - } - - loader_index = loader_find_or_create(NULL,NULL); - cnum = class_find_or_create(OBJECT_CLASS_SIG, loader_index); - object_class = class_get_class(env, cnum); - tracker_class = class_get_class(env, gdata->tracker_cnum); - - CHECK_EXCEPTIONS(env) { - registerNatives(env, tracker_class, registry, - (int)sizeof(registry)/(int)sizeof(registry[0])); - } END_CHECK_EXCEPTIONS; - - HPROF_ASSERT(tracker_class!=NULL); - - gdata->tracker_method_count = - (int)sizeof(tracker_methods)/(int)sizeof(tracker_methods[0]); - - HPROF_ASSERT(gdata->tracker_method_count <= - (int)(sizeof(gdata->tracker_methods)/sizeof(gdata->tracker_methods[0]))); - - CHECK_EXCEPTIONS(env) { - gdata->object_init_method = getMethodID(env, object_class, - OBJECT_INIT_NAME, OBJECT_INIT_SIG); - for ( i=0 ; i < gdata->tracker_method_count ; i++ ) { - gdata->tracker_methods[i].name = - string_find_or_create(tracker_methods[i].name); - gdata->tracker_methods[i].sig = - string_find_or_create(tracker_methods[i].sig); - gdata->tracker_methods[i].method = - getStaticMethodID(env, tracker_class, - tracker_methods[i].name, tracker_methods[i].sig); - HPROF_ASSERT(gdata->tracker_methods[i].method!=NULL); - LOG2("tracker_setup_methods(): Found", tracker_methods[i].name); - } - } END_CHECK_EXCEPTIONS; -}