hprof_tracker.c

来自「一个小公司要求给写的很简单的任务管理系统。」· C语言 代码 · 共 317 行

C
317
字号
/* * @(#)hprof_tracker.c	1.17 05/11/17 *  * Copyright (c) 2006 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: *  * -Redistribution of source code must retain the above copyright notice, this *  list of conditions and the following disclaimer. *  * -Redistribution 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, Inc. or the names of contributors may  * be used to endorse or promote products derived from this software without  * specific prior written permission. *  * This software is provided "AS IS," without a warranty of any kind. ALL  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *  * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. *//* 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 voidset_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);}voidtracker_engage(JNIEnv *env){    set_engaged(env, 0xFFFF);}voidtracker_disengage(JNIEnv *env){    set_engaged(env, 0);}jbooleantracker_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       }     };voidtracker_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);}voidtracker_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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?