alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (hprof_event.c)

This example Java source code file (hprof_event.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

class_loaded, classindex, end_with_local_refs, hprof_assert, illegal, jni_false, methodindex, null, objectindex, serialnumber, siteindex, tlsindex, traceindex, with_local_refs

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

 

new blog posts

 

Copyright 1998-2021 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.