0N/A/*
2362N/A * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A *
0N/A * Redistribution and use in source and binary forms, with or without
0N/A * modification, are permitted provided that the following conditions
0N/A * are met:
0N/A *
0N/A * - Redistributions of source code must retain the above copyright
0N/A * notice, this list of conditions and the following disclaimer.
0N/A *
0N/A * - Redistributions in binary form must reproduce the above copyright
0N/A * notice, this list of conditions and the following disclaimer in the
0N/A * documentation and/or other materials provided with the distribution.
0N/A *
2362N/A * - Neither the name of Oracle nor the names of its
0N/A * contributors may be used to endorse or promote products derived
0N/A * from this software without specific prior written permission.
0N/A *
0N/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0N/A * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0N/A * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0N/A * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0N/A * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0N/A * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0N/A * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0N/A * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0N/A * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0N/A * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0N/A */
0N/A
4378N/A/*
4378N/A * This source code is provided to illustrate the usage of a given feature
4378N/A * or technique and has been deliberately simplified. Additional steps
4378N/A * required for a production-quality application, such as security checks,
4378N/A * input validation and proper error handling, might not be present in
4378N/A * this sample code.
4378N/A */
4378N/A
4378N/A
0N/A/* General utility functions. */
0N/A
0N/A/*
0N/A * Wrappers over JVM, JNI, and JVMTI functions are placed here.
0N/A *
0N/A * All memory allocation and deallocation goes through jvmtiAllocate()
0N/A * and jvmtiDeallocate().
0N/A *
0N/A */
0N/A
0N/A
0N/A#include "hprof.h"
0N/A
0N/A/* Macro to get JNI function pointer. */
0N/A#define JNI_FUNC_PTR(env,f) (*((*(env))->f))
0N/A
0N/A/* Macro to get JVM function pointer. */
0N/A#define JVM_FUNC_PTR(env,f) (*((*(env))->f))
0N/A
0N/A/* Macro to get JVMTI function pointer. */
0N/A#define JVMTI_FUNC_PTR(env,f) (*((*(env))->f))
0N/A
0N/A/* ------------------------------------------------------------------- */
0N/A/* JVM functions */
0N/A
0N/AJNIEnv *
0N/AgetEnv(void)
0N/A{
0N/A JNIEnv *env;
0N/A jint res;
0N/A
0N/A res = JVM_FUNC_PTR(gdata->jvm,GetEnv)
0N/A (gdata->jvm, (void **)&env, JNI_VERSION_1_2);
0N/A if (res != JNI_OK) {
0N/A char buf[256];
0N/A
0N/A (void)md_snprintf(buf, sizeof(buf),
0N/A "Unable to access JNI Version 1.2 (0x%x),"
0N/A " is your JDK a 5.0 or newer version?"
0N/A " JNIEnv's GetEnv() returned %d",
0N/A JNI_VERSION_1_2, res);
0N/A buf[sizeof(buf)-1] = 0;
0N/A HPROF_ERROR(JNI_FALSE, buf);
0N/A error_exit_process(1); /* Kill entire process, no core dump */
0N/A }
0N/A return env;
0N/A}
0N/A
0N/A/* ------------------------------------------------------------------- */
0N/A/* Memory Allocation */
0N/A
0N/Avoid *
0N/AjvmtiAllocate(int size)
0N/A{
0N/A jvmtiError error;
0N/A unsigned char *ptr;
0N/A
0N/A HPROF_ASSERT(size>=0);
0N/A ptr = NULL;
0N/A if ( size == 0 ) {
0N/A return ptr;
0N/A }
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,Allocate)
0N/A (gdata->jvmti, (jlong)size, &ptr);
0N/A if ( error != JVMTI_ERROR_NONE || ptr == NULL ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot allocate jvmti memory");
0N/A }
0N/A return (void*)ptr;
0N/A}
0N/A
0N/Avoid
0N/AjvmtiDeallocate(void *ptr)
0N/A{
0N/A if ( ptr != NULL ) {
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,Deallocate)
0N/A (gdata->jvmti, (unsigned char*)ptr);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot deallocate jvmti memory");
0N/A }
0N/A }
0N/A}
0N/A
0N/A#ifdef DEBUG
0N/A
0N/Avoid *
0N/Ahprof_debug_malloc(int size, char *file, int line)
0N/A{
0N/A void *ptr;
0N/A
0N/A HPROF_ASSERT(size>0);
0N/A
0N/A rawMonitorEnter(gdata->debug_malloc_lock); {
0N/A ptr = debug_malloc(size, file, line);
0N/A } rawMonitorExit(gdata->debug_malloc_lock);
0N/A
0N/A if ( ptr == NULL ) {
0N/A HPROF_ERROR(JNI_TRUE, "Cannot allocate malloc memory");
0N/A }
0N/A return ptr;
0N/A}
0N/A
0N/Avoid
0N/Ahprof_debug_free(void *ptr, char *file, int line)
0N/A{
0N/A HPROF_ASSERT(ptr!=NULL);
0N/A
0N/A rawMonitorEnter(gdata->debug_malloc_lock); {
0N/A (void)debug_free(ptr, file, line);
0N/A } rawMonitorExit(gdata->debug_malloc_lock);
0N/A}
0N/A
0N/A#endif
0N/A
0N/Avoid *
0N/Ahprof_malloc(int size)
0N/A{
0N/A void *ptr;
0N/A
0N/A HPROF_ASSERT(size>0);
0N/A ptr = malloc(size);
0N/A if ( ptr == NULL ) {
0N/A HPROF_ERROR(JNI_TRUE, "Cannot allocate malloc memory");
0N/A }
0N/A return ptr;
0N/A}
0N/A
0N/Avoid
0N/Ahprof_free(void *ptr)
0N/A{
0N/A HPROF_ASSERT(ptr!=NULL);
0N/A (void)free(ptr);
0N/A}
0N/A
0N/A/* ------------------------------------------------------------------- */
0N/A/* JVMTI Version functions */
0N/A
0N/Ajint
0N/AjvmtiVersion(void)
0N/A{
0N/A if (gdata->cachedJvmtiVersion == 0) {
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)
0N/A (gdata->jvmti, &(gdata->cachedJvmtiVersion));
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get jvmti version number");
0N/A }
0N/A }
0N/A return gdata->cachedJvmtiVersion;
0N/A}
0N/A
0N/Astatic jint
0N/AjvmtiMajorVersion(void)
0N/A{
0N/A return (jvmtiVersion() & JVMTI_VERSION_MASK_MAJOR)
0N/A >> JVMTI_VERSION_SHIFT_MAJOR;
0N/A}
0N/A
0N/Astatic jint
0N/AjvmtiMinorVersion(void)
0N/A{
0N/A return (jvmtiVersion() & JVMTI_VERSION_MASK_MINOR)
0N/A >> JVMTI_VERSION_SHIFT_MINOR;
0N/A}
0N/A
0N/Astatic jint
0N/AjvmtiMicroVersion(void)
0N/A{
0N/A return (jvmtiVersion() & JVMTI_VERSION_MASK_MICRO)
0N/A >> JVMTI_VERSION_SHIFT_MICRO;
0N/A}
0N/A
0N/A/* Logic to determine JVMTI version compatibility */
0N/Astatic jboolean
0N/Acompatible_versions(jint major_runtime, jint minor_runtime,
0N/A jint major_compiletime, jint minor_compiletime)
0N/A{
0N/A /* Runtime major version must match. */
0N/A if ( major_runtime != major_compiletime ) {
0N/A return JNI_FALSE;
0N/A }
0N/A /* Runtime minor version must be >= the version compiled with. */
0N/A if ( minor_runtime < minor_compiletime ) {
0N/A return JNI_FALSE;
0N/A }
0N/A /* Assumed compatible */
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/A/* ------------------------------------------------------------------- */
0N/A/* JVMTI Raw Monitor support functions */
0N/A
0N/AjrawMonitorID
0N/AcreateRawMonitor(const char *str)
0N/A{
0N/A jvmtiError error;
0N/A jrawMonitorID m;
0N/A
0N/A m = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,CreateRawMonitor)
0N/A (gdata->jvmti, str, &m);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot create raw monitor");
0N/A }
0N/A return m;
0N/A}
0N/A
0N/Avoid
0N/ArawMonitorEnter(jrawMonitorID m)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorEnter)
0N/A (gdata->jvmti, m);
0N/A if ( error == JVMTI_ERROR_WRONG_PHASE ) {
0N/A /* Treat this as ok, after agent shutdown CALLBACK code may call this */
0N/A error = JVMTI_ERROR_NONE;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot enter with raw monitor");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/ArawMonitorWait(jrawMonitorID m, jlong pause_time)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorWait)
0N/A (gdata->jvmti, m, pause_time);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot wait with raw monitor");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/ArawMonitorNotifyAll(jrawMonitorID m)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorNotifyAll)
0N/A (gdata->jvmti, m);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot notify all with raw monitor");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/ArawMonitorExit(jrawMonitorID m)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorExit)
0N/A (gdata->jvmti, m);
0N/A if ( error == JVMTI_ERROR_WRONG_PHASE ) {
0N/A /* Treat this as ok, after agent shutdown CALLBACK code may call this */
0N/A error = JVMTI_ERROR_NONE;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot exit with raw monitor");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AdestroyRawMonitor(jrawMonitorID m)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,DestroyRawMonitor)
0N/A (gdata->jvmti, m);
0N/A if ( error == JVMTI_ERROR_WRONG_PHASE ) {
0N/A /* Treat this as ok */
0N/A error = JVMTI_ERROR_NONE;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot destroy raw monitor");
0N/A }
0N/A}
0N/A
0N/A/* ------------------------------------------------------------------- */
0N/A/* JVMTI Event enabling/disabilin */
0N/A
0N/Avoid
0N/AsetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event, jthread thread)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
0N/A (gdata->jvmti, mode, event, thread);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot set event notification");
0N/A }
0N/A}
0N/A
0N/A/* ---------------------------------------------------------------------- */
0N/A/* JNI Support Functions */
0N/A
0N/Ajobject
0N/AexceptionOccurred(JNIEnv *env)
0N/A{
0N/A return JNI_FUNC_PTR(env,ExceptionOccurred)(env);
0N/A}
0N/A
0N/Avoid
0N/AexceptionDescribe(JNIEnv *env)
0N/A{
0N/A JNI_FUNC_PTR(env,ExceptionDescribe)(env);
0N/A}
0N/A
0N/Avoid
0N/AexceptionClear(JNIEnv *env)
0N/A{
0N/A JNI_FUNC_PTR(env,ExceptionClear)(env);
0N/A}
0N/A
0N/Ajobject
0N/AnewGlobalReference(JNIEnv *env, jobject object)
0N/A{
0N/A jobject gref;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A gref = JNI_FUNC_PTR(env,NewGlobalRef)(env, object);
0N/A HPROF_ASSERT(gref!=NULL);
0N/A return gref;
0N/A}
0N/A
0N/Ajobject
0N/AnewWeakGlobalReference(JNIEnv *env, jobject object)
0N/A{
0N/A jobject gref;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A gref = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, object);
0N/A HPROF_ASSERT(gref!=NULL);
0N/A return gref;
0N/A}
0N/A
0N/Avoid
0N/AdeleteGlobalReference(JNIEnv *env, jobject object)
0N/A{
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A JNI_FUNC_PTR(env,DeleteGlobalRef)(env, object);
0N/A}
0N/A
0N/Ajobject
0N/AnewLocalReference(JNIEnv *env, jobject object)
0N/A{
0N/A jobject lref;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A lref = JNI_FUNC_PTR(env,NewLocalRef)(env, object);
0N/A /* Possible for a non-null weak reference to return a NULL localref */
0N/A return lref;
0N/A}
0N/A
0N/Avoid
0N/AdeleteLocalReference(JNIEnv *env, jobject object)
0N/A{
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A JNI_FUNC_PTR(env,DeleteLocalRef)(env, object);
0N/A}
0N/A
0N/Avoid
0N/AdeleteWeakGlobalReference(JNIEnv *env, jobject object)
0N/A{
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, object);
0N/A}
0N/A
0N/Ajclass
0N/AgetObjectClass(JNIEnv *env, jobject object)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jclass clazz;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A return clazz;
0N/A}
0N/A
0N/Ajclass
0N/AgetSuperclass(JNIEnv *env, jclass klass)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jclass super_klass;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(klass!=NULL);
0N/A super_klass = JNI_FUNC_PTR(env,GetSuperclass)(env, klass);
0N/A return super_klass;
0N/A}
0N/A
0N/AjmethodID
0N/AgetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
0N/A{
0N/A jmethodID method;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A HPROF_ASSERT(name!=NULL);
0N/A HPROF_ASSERT(sig!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A method = JNI_FUNC_PTR(env,GetStaticMethodID)(env, clazz, name, sig);
0N/A } END_CHECK_EXCEPTIONS;
0N/A HPROF_ASSERT(method!=NULL);
0N/A return method;
0N/A}
0N/A
0N/AjmethodID
0N/AgetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
0N/A{
0N/A jmethodID method;
0N/A jobject exception;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A HPROF_ASSERT(name!=NULL);
0N/A HPROF_ASSERT(sig!=NULL);
0N/A method = JNI_FUNC_PTR(env,GetMethodID)(env, clazz, name, sig);
0N/A /* Might be a static method */
0N/A exception = JNI_FUNC_PTR(env,ExceptionOccurred)(env);
0N/A if ( exception != NULL ) {
0N/A JNI_FUNC_PTR(env,ExceptionClear)(env);
0N/A method = getStaticMethodID(env, clazz, name, sig);
0N/A }
0N/A HPROF_ASSERT(method!=NULL);
0N/A return method;
0N/A}
0N/A
0N/Ajclass
0N/AfindClass(JNIEnv *env, const char *name)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jclass clazz;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(name!=NULL);
0N/A LOG2("FindClass", name);
0N/A CHECK_EXCEPTIONS(env) {
0N/A clazz = JNI_FUNC_PTR(env,FindClass)(env, name);
0N/A } END_CHECK_EXCEPTIONS;
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A return clazz;
0N/A}
0N/A
0N/AjfieldID
0N/AgetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
0N/A{
0N/A jfieldID field;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A HPROF_ASSERT(name!=NULL);
0N/A HPROF_ASSERT(sig!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A field = JNI_FUNC_PTR(env,GetStaticFieldID)(env, clazz, name, sig);
0N/A } END_CHECK_EXCEPTIONS;
0N/A return field;
0N/A}
0N/A
0N/Avoid
0N/AsetStaticIntField(JNIEnv *env, jclass clazz, jfieldID field, jint value)
0N/A{
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A HPROF_ASSERT(field!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A JNI_FUNC_PTR(env,SetStaticIntField)(env, clazz, field, value);
0N/A } END_CHECK_EXCEPTIONS;
0N/A}
0N/A
0N/Astatic jobject
0N/AcallStaticObjectMethod(JNIEnv *env, jclass klass, jmethodID method)
0N/A{
0N/A jobject x;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(klass!=NULL);
0N/A HPROF_ASSERT(method!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A x = JNI_FUNC_PTR(env,CallStaticObjectMethod)(env, klass, method);
0N/A } END_CHECK_EXCEPTIONS;
0N/A return x;
0N/A}
0N/A
0N/Astatic jlong
0N/AcallLongMethod(JNIEnv *env, jobject object, jmethodID method)
0N/A{
0N/A jlong x;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A HPROF_ASSERT(method!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A x = JNI_FUNC_PTR(env,CallLongMethod)(env, object, method);
0N/A } END_CHECK_EXCEPTIONS;
0N/A return x;
0N/A}
0N/A
0N/Astatic void
0N/AcallVoidMethod(JNIEnv *env, jobject object, jmethodID method, jboolean arg)
0N/A{
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(object!=NULL);
0N/A HPROF_ASSERT(method!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A JNI_FUNC_PTR(env,CallVoidMethod)(env, object, method, arg);
0N/A } END_CHECK_EXCEPTIONS;
0N/A}
0N/A
0N/Astatic jstring
0N/AnewStringUTF(JNIEnv *env, const char *name)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jstring string;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(name!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A string = JNI_FUNC_PTR(env,NewStringUTF)(env, name);
0N/A } END_CHECK_EXCEPTIONS;
0N/A HPROF_ASSERT(string!=NULL);
0N/A return string;
0N/A}
0N/A
0N/Astatic jobject
0N/AnewThreadObject(JNIEnv *env, jclass clazz, jmethodID method,
0N/A jthreadGroup group, jstring name)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jthread thread;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A HPROF_ASSERT(method!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A thread = JNI_FUNC_PTR(env,NewObject)(env, clazz, method, group, name);
0N/A } END_CHECK_EXCEPTIONS;
0N/A HPROF_ASSERT(thread!=NULL);
0N/A return thread;
0N/A}
0N/A
0N/Ajboolean
0N/AisSameObject(JNIEnv *env, jobject o1, jobject o2)
0N/A{
0N/A HPROF_ASSERT(env!=NULL);
0N/A if ( o1 == o2 || JNI_FUNC_PTR(env,IsSameObject)(env, o1, o2) ) {
0N/A return JNI_TRUE;
0N/A }
0N/A return JNI_FALSE;
0N/A}
0N/A
0N/Avoid
0N/ApushLocalFrame(JNIEnv *env, jint capacity)
0N/A{
0N/A HPROF_ASSERT(env!=NULL);
0N/A CHECK_EXCEPTIONS(env) {
0N/A jint ret;
0N/A
0N/A ret = JNI_FUNC_PTR(env,PushLocalFrame)(env, capacity);
0N/A if ( ret != 0 ) {
0N/A HPROF_ERROR(JNI_TRUE, "JNI PushLocalFrame returned non-zero");
0N/A }
0N/A } END_CHECK_EXCEPTIONS;
0N/A}
0N/A
0N/Avoid
0N/ApopLocalFrame(JNIEnv *env, jobject result)
0N/A{
0N/A jobject ret;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A ret = JNI_FUNC_PTR(env,PopLocalFrame)(env, result);
0N/A if ( (result != NULL && ret == NULL) || (result == NULL && ret != NULL) ) {
0N/A HPROF_ERROR(JNI_TRUE, "JNI PopLocalFrame returned wrong object");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AregisterNatives(JNIEnv *env, jclass clazz,
0N/A JNINativeMethod *methods, jint count)
0N/A{
0N/A jint ret;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A HPROF_ASSERT(methods!=NULL);
0N/A HPROF_ASSERT(count>0);
0N/A ret = JNI_FUNC_PTR(env,RegisterNatives)(env, clazz, methods, count);
0N/A if ( ret != 0 ) {
0N/A HPROF_ERROR(JNI_TRUE, "JNI RegisterNatives returned non-zero");
0N/A }
0N/A}
0N/A
0N/A/* ---------------------------------------------------------------------- */
0N/A/* JVMTI Support Functions */
0N/A
0N/Achar *
0N/AgetErrorName(jvmtiError error_number)
0N/A{
0N/A char *error_name;
0N/A
0N/A error_name = NULL;
0N/A (void)JVMTI_FUNC_PTR(gdata->jvmti,GetErrorName)
0N/A (gdata->jvmti, error_number, &error_name);
0N/A return error_name;
0N/A}
0N/A
0N/AjvmtiPhase
0N/AgetPhase(void)
0N/A{
0N/A jvmtiPhase phase;
0N/A
0N/A phase = 0;
0N/A (void)JVMTI_FUNC_PTR(gdata->jvmti,GetPhase)(gdata->jvmti, &phase);
0N/A return phase;
0N/A}
0N/A
0N/Achar *
0N/AphaseString(jvmtiPhase phase)
0N/A{
0N/A switch ( phase ) {
0N/A case JVMTI_PHASE_ONLOAD:
0N/A return "onload";
0N/A case JVMTI_PHASE_PRIMORDIAL:
0N/A return "primordial";
0N/A case JVMTI_PHASE_START:
0N/A return "start";
0N/A case JVMTI_PHASE_LIVE:
0N/A return "live";
0N/A case JVMTI_PHASE_DEAD:
0N/A return "dead";
0N/A }
0N/A return "unknown";
0N/A}
0N/A
0N/Avoid
0N/AdisposeEnvironment(void)
0N/A{
0N/A (void)JVMTI_FUNC_PTR(gdata->jvmti,DisposeEnvironment)
0N/A (gdata->jvmti);
0N/A}
0N/A
0N/Ajlong
0N/AgetObjectSize(jobject object)
0N/A{
0N/A jlong size;
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(object!=NULL);
0N/A size = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetObjectSize)
0N/A (gdata->jvmti, object, &size);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get object size");
0N/A }
0N/A return size;
0N/A}
0N/A
0N/Astatic jboolean
0N/AisInterface(jclass klass)
0N/A{
0N/A jvmtiError error;
0N/A jboolean answer;
0N/A
0N/A HPROF_ASSERT(klass!=NULL);
0N/A answer = JNI_FALSE;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,IsInterface)
0N/A (gdata->jvmti, klass, &answer);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot call IsInterface");
0N/A }
0N/A return answer;
0N/A}
0N/A
0N/Ajint
0N/AgetClassStatus(jclass klass)
0N/A{
0N/A jvmtiError error;
0N/A jint status;
0N/A
0N/A HPROF_ASSERT(klass!=NULL);
0N/A status = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassStatus)
0N/A (gdata->jvmti, klass, &status);
0N/A if ( error == JVMTI_ERROR_WRONG_PHASE ) {
0N/A /* Treat this as ok */
0N/A error = JVMTI_ERROR_NONE;
0N/A status = 0;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get class status");
0N/A }
0N/A return status;
0N/A}
0N/A
0N/Ajobject
0N/AgetClassLoader(jclass klass)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jvmtiError error;
0N/A jobject loader;
0N/A
0N/A HPROF_ASSERT(klass!=NULL);
0N/A loader = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassLoader)
0N/A (gdata->jvmti, klass, &loader);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get class loader");
0N/A }
0N/A return loader;
0N/A}
0N/A
0N/Ajlong
0N/AgetTag(jobject object)
0N/A{
0N/A jlong tag;
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(object!=NULL);
0N/A tag = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetTag)
0N/A (gdata->jvmti, object, &tag);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get object tag");
0N/A }
0N/A return tag;
0N/A}
0N/A
0N/Avoid
0N/AsetTag(jobject object, jlong tag)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(object!=NULL);
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,SetTag)
0N/A (gdata->jvmti, object, tag);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot set object tag");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetObjectMonitorUsage(jobject object, jvmtiMonitorUsage *uinfo)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(object!=NULL);
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetObjectMonitorUsage)
0N/A (gdata->jvmti, object, uinfo);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get monitor usage info");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetOwnedMonitorInfo(jthread thread, jobject **ppobjects, jint *pcount)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A HPROF_ASSERT(ppobjects!=NULL);
0N/A HPROF_ASSERT(pcount!=NULL);
0N/A *pcount = 0;
0N/A *ppobjects = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorInfo)
0N/A (gdata->jvmti, thread, pcount, ppobjects);
0N/A if ( error == JVMTI_ERROR_THREAD_NOT_ALIVE ) {
0N/A *pcount = 0;
0N/A error = JVMTI_ERROR_NONE;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get thread owned monitor info");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetSystemProperty(const char *name, char **value)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(name!=NULL);
0N/A *value = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetSystemProperty)
0N/A (gdata->jvmti, name, value);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get system property");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetClassSignature(jclass klass, char** psignature, char **pgeneric_signature)
0N/A{
0N/A jvmtiError error;
0N/A char *generic_signature;
0N/A
0N/A HPROF_ASSERT(klass!=NULL);
0N/A *psignature = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassSignature)
0N/A (gdata->jvmti, klass, psignature, &generic_signature);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get class signature");
0N/A }
0N/A if ( pgeneric_signature != NULL ) {
0N/A *pgeneric_signature = generic_signature;
0N/A } else {
0N/A jvmtiDeallocate(generic_signature);
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetSourceFileName(jclass klass, char** pname)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(klass!=NULL);
0N/A *pname = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
0N/A (gdata->jvmti, klass, pname);
0N/A if ( error == JVMTI_ERROR_ABSENT_INFORMATION ) {
0N/A error = JVMTI_ERROR_NONE;
0N/A *pname = NULL;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get source file name");
0N/A }
0N/A}
0N/A
0N/Astatic void
0N/AgetClassFields(jclass klass, jint* pn_fields, jfieldID** pfields)
0N/A{
0N/A jvmtiError error;
0N/A jint status;
0N/A
0N/A HPROF_ASSERT(klass!=NULL);
0N/A *pn_fields = 0;
0N/A *pfields = NULL;
0N/A
0N/A /* Get class status */
0N/A status = getClassStatus(klass);
0N/A
0N/A /* Arrays have no fields */
0N/A if ( status & JVMTI_CLASS_STATUS_ARRAY ) {
0N/A return;
0N/A }
0N/A
0N/A /* Primitives have no fields */
0N/A if ( status & JVMTI_CLASS_STATUS_PRIMITIVE ) {
0N/A return;
0N/A }
0N/A
0N/A /* If the class is not prepared, we have a problem? */
0N/A if ( !(status & JVMTI_CLASS_STATUS_PREPARED) ) {
0N/A HPROF_ERROR(JNI_FALSE, "Class not prepared when needing fields");
0N/A return;
0N/A }
0N/A
0N/A /* Now try and get all the fields */
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassFields)
0N/A (gdata->jvmti, klass, pn_fields, pfields);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get class field list");
0N/A }
0N/A}
0N/A
0N/Astatic jint
0N/AgetFieldModifiers(jclass klass, jfieldID field)
0N/A{
0N/A jvmtiError error;
0N/A jint modifiers;
0N/A
0N/A HPROF_ASSERT(klass!=NULL);
0N/A HPROF_ASSERT(field!=NULL);
0N/A modifiers = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldModifiers)
0N/A (gdata->jvmti, klass, field, &modifiers);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get field modifiers");
0N/A }
0N/A return modifiers;
0N/A}
0N/A
0N/Astatic void
0N/AgetFieldName(jclass klass, jfieldID field, char** pname, char** psignature,
0N/A char **pgeneric_signature)
0N/A{
0N/A jvmtiError error;
0N/A char *generic_signature;
0N/A
0N/A generic_signature = NULL;
0N/A *pname = NULL;
0N/A *psignature = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldName)
0N/A (gdata->jvmti, klass, field, pname, psignature, &generic_signature);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get field name");
0N/A }
0N/A if ( pgeneric_signature != NULL ) {
0N/A *pgeneric_signature = generic_signature;
0N/A } else {
0N/A jvmtiDeallocate(generic_signature);
0N/A }
0N/A}
0N/A
0N/Astatic void
0N/AgetImplementedInterfaces(jclass klass, jint* pn_interfaces,
0N/A jclass** pinterfaces)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jvmtiError error;
0N/A
0N/A *pn_interfaces = 0;
0N/A *pinterfaces = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetImplementedInterfaces)
0N/A (gdata->jvmti, klass, pn_interfaces, pinterfaces);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get class interface list");
0N/A }
0N/A}
0N/A
0N/Astatic ClassIndex
0N/Aget_cnum(JNIEnv *env, jclass klass)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A ClassIndex cnum;
0N/A LoaderIndex loader_index;
0N/A char *sig;
0N/A jobject loader;
0N/A
0N/A loader = getClassLoader(klass);
0N/A loader_index = loader_find_or_create(env, loader);
0N/A getClassSignature(klass, &sig, NULL);
0N/A cnum = class_find_or_create(sig, loader_index);
0N/A jvmtiDeallocate(sig);
0N/A (void)class_new_classref(env, cnum, klass);
0N/A return cnum;
0N/A}
0N/A
0N/A/* From primitive type, get signature letter */
0N/Achar
0N/AprimTypeToSigChar(jvmtiPrimitiveType primType)
0N/A{
0N/A char sig_ch;
0N/A
0N/A sig_ch = 0;
0N/A switch ( primType ) {
0N/A case JVMTI_PRIMITIVE_TYPE_BYTE:
0N/A sig_ch = JVM_SIGNATURE_BYTE;
0N/A break;
0N/A case JVMTI_PRIMITIVE_TYPE_CHAR:
0N/A sig_ch = JVM_SIGNATURE_CHAR;
0N/A break;
0N/A case JVMTI_PRIMITIVE_TYPE_FLOAT:
0N/A sig_ch = JVM_SIGNATURE_FLOAT;
0N/A break;
0N/A case JVMTI_PRIMITIVE_TYPE_DOUBLE:
0N/A sig_ch = JVM_SIGNATURE_DOUBLE;
0N/A break;
0N/A case JVMTI_PRIMITIVE_TYPE_INT:
0N/A sig_ch = JVM_SIGNATURE_INT;
0N/A break;
0N/A case JVMTI_PRIMITIVE_TYPE_LONG:
0N/A sig_ch = JVM_SIGNATURE_LONG;
0N/A break;
0N/A case JVMTI_PRIMITIVE_TYPE_SHORT:
0N/A sig_ch = JVM_SIGNATURE_SHORT;
0N/A break;
0N/A case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
0N/A sig_ch = JVM_SIGNATURE_BOOLEAN;
0N/A break;
0N/A default:
0N/A sig_ch = 0;
0N/A break;
0N/A }
0N/A return sig_ch;
0N/A}
0N/A
0N/A/* From signature, get primitive type */
0N/AjvmtiPrimitiveType
0N/AsigToPrimType(char *sig)
0N/A{
0N/A jvmtiPrimitiveType primType;
0N/A
0N/A primType = 0;
0N/A if ( sig == NULL || sig[0] == 0 ) {
0N/A return primType;
0N/A }
0N/A switch ( sig[0] ) {
0N/A case JVM_SIGNATURE_BYTE:
0N/A primType = JVMTI_PRIMITIVE_TYPE_BYTE;
0N/A break;
0N/A case JVM_SIGNATURE_CHAR:
0N/A primType = JVMTI_PRIMITIVE_TYPE_CHAR;
0N/A break;
0N/A case JVM_SIGNATURE_FLOAT:
0N/A primType = JVMTI_PRIMITIVE_TYPE_FLOAT;
0N/A break;
0N/A case JVM_SIGNATURE_DOUBLE:
0N/A primType = JVMTI_PRIMITIVE_TYPE_DOUBLE;
0N/A break;
0N/A case JVM_SIGNATURE_INT:
0N/A primType = JVMTI_PRIMITIVE_TYPE_INT;
0N/A break;
0N/A case JVM_SIGNATURE_LONG:
0N/A primType = JVMTI_PRIMITIVE_TYPE_LONG;
0N/A break;
0N/A case JVM_SIGNATURE_SHORT:
0N/A primType = JVMTI_PRIMITIVE_TYPE_SHORT;
0N/A break;
0N/A case JVM_SIGNATURE_BOOLEAN:
0N/A primType = JVMTI_PRIMITIVE_TYPE_BOOLEAN;
0N/A break;
0N/A }
0N/A return primType;
0N/A}
0N/A
0N/A/* From signature, get primitive size */
0N/Aint
0N/AsigToPrimSize(char *sig)
0N/A{
0N/A unsigned size;
0N/A
0N/A size = 0;
0N/A if ( sig == NULL || sig[0] == 0 ) {
0N/A return size;
0N/A }
0N/A switch ( sig[0] ) {
0N/A case JVM_SIGNATURE_BYTE:
0N/A case JVM_SIGNATURE_BOOLEAN:
0N/A size = 1;
0N/A break;
0N/A case JVM_SIGNATURE_CHAR:
0N/A case JVM_SIGNATURE_SHORT:
0N/A size = 2;
0N/A break;
0N/A case JVM_SIGNATURE_FLOAT:
0N/A case JVM_SIGNATURE_INT:
0N/A size = 4;
0N/A break;
0N/A case JVM_SIGNATURE_DOUBLE:
0N/A case JVM_SIGNATURE_LONG:
0N/A size = 8;
0N/A break;
0N/A }
0N/A return size;
0N/A}
0N/A
0N/Astatic void
0N/Aadd_class_fields(JNIEnv *env, ClassIndex top_cnum, ClassIndex cnum,
0N/A jclass klass, Stack *field_list, Stack *class_list)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jclass *interfaces;
0N/A jint n_interfaces;
0N/A jfieldID *idlist;
0N/A jint n_fields;
0N/A int i;
0N/A int depth;
0N/A int skip_static_field_names;
0N/A jint status;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A HPROF_ASSERT(klass!=NULL);
0N/A HPROF_ASSERT(field_list!=NULL);
0N/A HPROF_ASSERT(class_list!=NULL);
0N/A
0N/A /* If not the initial class, we can skip the static fields (perf issue) */
0N/A skip_static_field_names = (cnum != top_cnum);
0N/A
0N/A /* Get class status */
0N/A status = getClassStatus(klass);
0N/A
0N/A /* Arrays have no fields */
0N/A if ( status & JVMTI_CLASS_STATUS_ARRAY ) {
0N/A return;
0N/A }
0N/A
0N/A /* Primitives have no fields */
0N/A if ( status & JVMTI_CLASS_STATUS_PRIMITIVE ) {
0N/A return;
0N/A }
0N/A
0N/A /* If the class is not prepared, we have a problem? */
0N/A if ( !(status & JVMTI_CLASS_STATUS_PREPARED) ) {
0N/A char *sig;
0N/A
0N/A getClassSignature(klass, &sig, NULL);
0N/A debug_message("Class signature is: %s\n", sig);
0N/A HPROF_ERROR(JNI_FALSE, "Class not prepared when needing all fields");
0N/A jvmtiDeallocate(sig);
0N/A return;
0N/A }
0N/A
0N/A /* See if class already processed */
0N/A depth = stack_depth(class_list);
0N/A for ( i = depth-1 ; i >= 0 ; i-- ) {
0N/A if ( isSameObject(env, klass, *(jclass*)stack_element(class_list, i)) ) {
0N/A return;
0N/A }
0N/A }
0N/A
0N/A /* Class or Interface, do implemented interfaces recursively */
0N/A getImplementedInterfaces(klass, &n_interfaces, &interfaces);
0N/A for ( i = 0 ; i < n_interfaces ; i++ ) {
0N/A add_class_fields(env, top_cnum,
0N/A get_cnum(env, interfaces[i]), interfaces[i],
0N/A field_list, class_list);
0N/A }
0N/A jvmtiDeallocate(interfaces);
0N/A
0N/A /* Begin graph traversal, go up super chain recursively */
0N/A if ( !isInterface(klass) ) {
0N/A jclass super_klass;
0N/A
0N/A super_klass = getSuperclass(env, klass);
0N/A if ( super_klass != NULL ) {
0N/A add_class_fields(env, top_cnum,
0N/A get_cnum(env, super_klass), super_klass,
0N/A field_list, class_list);
0N/A }
0N/A }
0N/A
0N/A
0N/A /* Only now we add klass to list so we don't repeat it later */
0N/A stack_push(class_list, &klass);
0N/A
0N/A /* Now actually add the fields for this klass */
0N/A getClassFields(klass, &n_fields, &idlist);
0N/A for ( i = 0 ; i < n_fields ; i++ ) {
0N/A FieldInfo finfo;
0N/A static FieldInfo empty_finfo;
0N/A
0N/A finfo = empty_finfo;
0N/A finfo.cnum = cnum;
439N/A finfo.modifiers = (unsigned short)getFieldModifiers(klass, idlist[i]);
0N/A if ( ( finfo.modifiers & JVM_ACC_STATIC ) == 0 ||
0N/A !skip_static_field_names ) {
0N/A char *field_name;
0N/A char *field_sig;
0N/A
0N/A getFieldName(klass, idlist[i], &field_name, &field_sig, NULL);
0N/A finfo.name_index = string_find_or_create(field_name);
0N/A finfo.sig_index = string_find_or_create(field_sig);
0N/A finfo.primType = sigToPrimType(field_sig);
0N/A finfo.primSize = sigToPrimSize(field_sig);
0N/A jvmtiDeallocate(field_name);
0N/A jvmtiDeallocate(field_sig);
0N/A }
0N/A stack_push(field_list, &finfo);
0N/A }
0N/A jvmtiDeallocate(idlist);
0N/A}
0N/A
0N/Avoid
0N/AgetAllClassFieldInfo(JNIEnv *env, jclass klass,
0N/A jint* pn_fields, FieldInfo** pfields)
0N/A{
0N/A ClassIndex cnum;
0N/A
0N/A *pfields = NULL;
0N/A *pn_fields = 0;
0N/A
0N/A WITH_LOCAL_REFS(env, 1) {
0N/A Stack *class_list;
0N/A Stack *field_list;
0N/A int nbytes;
0N/A
0N/A cnum = get_cnum(env, klass);
0N/A class_list = stack_init( 16, 16, (int)sizeof(jclass));
0N/A field_list = stack_init(128, 128, (int)sizeof(FieldInfo));
0N/A add_class_fields(env, cnum, cnum, klass, field_list, class_list);
0N/A *pn_fields = stack_depth(field_list);
0N/A if ( (*pn_fields) > 0 ) {
0N/A nbytes = (*pn_fields) * (int)sizeof(FieldInfo);
0N/A *pfields = (FieldInfo*)HPROF_MALLOC(nbytes);
0N/A (void)memcpy(*pfields, stack_element(field_list, 0), nbytes);
0N/A }
0N/A stack_term(field_list);
0N/A stack_term(class_list);
0N/A } END_WITH_LOCAL_REFS;
0N/A}
0N/A
0N/Avoid
0N/AgetMethodClass(jmethodID method, jclass *pclazz)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(method!=NULL);
0N/A *pclazz = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodDeclaringClass)
0N/A (gdata->jvmti, method, pclazz);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get method class");
0N/A }
0N/A}
0N/A
0N/Ajboolean
0N/AisMethodNative(jmethodID method)
0N/A{
0N/A jvmtiError error;
0N/A jboolean isNative;
0N/A
0N/A HPROF_ASSERT(method!=NULL);
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodNative)
0N/A (gdata->jvmti, method, &isNative);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot check is method native");
0N/A }
0N/A return isNative;
0N/A}
0N/A
0N/Avoid
0N/AgetMethodName(jmethodID method, char** pname, char** psignature)
0N/A{
0N/A jvmtiError error;
0N/A char *generic_signature;
0N/A
0N/A HPROF_ASSERT(method!=NULL);
0N/A generic_signature = NULL;
0N/A *pname = NULL;
0N/A *psignature = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodName)
0N/A (gdata->jvmti, method, pname, psignature, &generic_signature);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get method name");
0N/A }
0N/A jvmtiDeallocate(generic_signature);
0N/A}
0N/A
0N/Avoid
0N/AgetPotentialCapabilities(jvmtiCapabilities *pcapabilities)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A (void)memset(pcapabilities,0,sizeof(jvmtiCapabilities));
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetPotentialCapabilities)
0N/A (gdata->jvmti, pcapabilities);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A HPROF_ERROR(JNI_FALSE, "Unable to get potential JVMTI capabilities.");
0N/A error_exit_process(1); /* Kill entire process, no core dump wanted */
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AaddCapabilities(jvmtiCapabilities *pcapabilities)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,AddCapabilities)
0N/A (gdata->jvmti, pcapabilities);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A HPROF_ERROR(JNI_FALSE, "Unable to get necessary JVMTI capabilities.");
0N/A error_exit_process(1); /* Kill entire process, no core dump wanted */
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AsetEventCallbacks(jvmtiEventCallbacks *pcallbacks)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)
0N/A (gdata->jvmti, pcallbacks, (int)sizeof(jvmtiEventCallbacks));
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot set jvmti callbacks");
0N/A }
0N/A
0N/A}
0N/A
0N/Avoid *
0N/AgetThreadLocalStorage(jthread thread)
0N/A{
0N/A jvmtiError error;
0N/A void *ptr;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A ptr = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadLocalStorage)
0N/A (gdata->jvmti, thread, &ptr);
0N/A if ( error == JVMTI_ERROR_WRONG_PHASE ) {
0N/A /* Treat this as ok */
0N/A error = JVMTI_ERROR_NONE;
0N/A ptr = NULL;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get thread local storage");
0N/A }
0N/A return ptr;
0N/A}
0N/A
0N/Avoid
0N/AsetThreadLocalStorage(jthread thread, void *ptr)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,SetThreadLocalStorage)
0N/A (gdata->jvmti, thread, (const void *)ptr);
0N/A if ( error == JVMTI_ERROR_WRONG_PHASE ) {
0N/A /* Treat this as ok */
0N/A error = JVMTI_ERROR_NONE;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot set thread local storage");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetThreadState(jthread thread, jint *threadState)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A HPROF_ASSERT(threadState!=NULL);
0N/A *threadState = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadState)
0N/A (gdata->jvmti, thread, threadState);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get thread state");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetThreadInfo(jthread thread, jvmtiThreadInfo *info)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A HPROF_ASSERT(info!=NULL);
0N/A (void)memset((void*)info, 0, sizeof(jvmtiThreadInfo));
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadInfo)
0N/A (gdata->jvmti, thread, info);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get thread info");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetThreadGroupInfo(jthreadGroup thread_group, jvmtiThreadGroupInfo *info)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(info!=NULL);
0N/A (void)memset((void*)info, 0, sizeof(jvmtiThreadGroupInfo));
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadGroupInfo)
0N/A (gdata->jvmti, thread_group, info);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get thread group info");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetLoadedClasses(jclass **ppclasses, jint *pcount)
0N/A/* WARNING: Must be called inside WITH_LOCAL_REFS */
0N/A{
0N/A jvmtiError error;
0N/A
0N/A *ppclasses = NULL;
0N/A *pcount = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetLoadedClasses)
0N/A (gdata->jvmti, pcount, ppclasses);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get all loaded class list");
0N/A }
0N/A}
0N/A
0N/Astatic void
0N/AgetLineNumberTable(jmethodID method, jvmtiLineNumberEntry **ppentries,
0N/A jint *pcount)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(method!=NULL);
0N/A *ppentries = NULL;
0N/A *pcount = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetLineNumberTable)
0N/A (gdata->jvmti, method, pcount, ppentries);
0N/A if ( error == JVMTI_ERROR_ABSENT_INFORMATION ) {
0N/A error = JVMTI_ERROR_NONE;
0N/A *ppentries = NULL;
0N/A *pcount = 0;
0N/A }
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get source line numbers");
0N/A }
0N/A}
0N/A
0N/Astatic jint
0N/Amap_loc2line(jlocation location, jvmtiLineNumberEntry *table, jint count)
0N/A{
0N/A jint line_number;
0N/A int i;
0N/A int start;
0N/A int half;
0N/A
0N/A HPROF_ASSERT(location>=0);
0N/A HPROF_ASSERT(count>=0);
0N/A
0N/A line_number = -1;
0N/A if ( count == 0 ) {
0N/A return line_number;
0N/A }
0N/A
0N/A /* Do a binary search */
0N/A half = count >> 1;
0N/A start = 0;
0N/A while ( half > 0 ) {
0N/A jlocation start_location;
0N/A
0N/A start_location = table[start + half].start_location;
0N/A if ( location > start_location ) {
0N/A start = start + half;
0N/A } else if ( location == start_location ) {
0N/A start = start + half;
0N/A break;
0N/A }
0N/A half = half >> 1;
0N/A }
0N/A
0N/A HPROF_ASSERT(start < count);
0N/A
0N/A /* Now start the table search */
0N/A for ( i = start ; i < count ; i++ ) {
0N/A if ( location < table[i].start_location ) {
0N/A HPROF_ASSERT( ((int)location) < ((int)table[i].start_location) );
0N/A break;
0N/A }
0N/A line_number = table[i].line_number;
0N/A }
0N/A HPROF_ASSERT(line_number > 0);
0N/A return line_number;
0N/A}
0N/A
0N/Ajint
0N/AgetLineNumber(jmethodID method, jlocation location)
0N/A{
0N/A jvmtiLineNumberEntry *line_table;
0N/A jint line_count;
0N/A jint lineno;
0N/A
0N/A HPROF_ASSERT(method!=NULL);
0N/A if ( location < 0 ) {
0N/A HPROF_ASSERT(location > -4);
0N/A return (jint)location;
0N/A }
0N/A lineno = -1;
0N/A
0N/A getLineNumberTable(method, &line_table, &line_count);
0N/A lineno = map_loc2line(location, line_table, line_count);
0N/A jvmtiDeallocate(line_table);
0N/A
0N/A return lineno;
0N/A}
0N/A
0N/Ajlong
0N/AgetMaxMemory(JNIEnv *env)
0N/A{
0N/A jlong max;
0N/A
0N/A HPROF_ASSERT(env!=NULL);
0N/A
0N/A max = (jlong)0;
0N/A WITH_LOCAL_REFS(env, 1) {
0N/A jclass clazz;
0N/A jmethodID getRuntime;
0N/A jobject runtime;
0N/A jmethodID maxMemory;
0N/A
0N/A clazz = findClass(env, "java/lang/Runtime");
0N/A getRuntime = getStaticMethodID(env, clazz, "getRuntime",
0N/A "()Ljava/lang/Runtime;");
0N/A runtime = callStaticObjectMethod(env, clazz, getRuntime);
0N/A maxMemory = getMethodID(env, clazz, "maxMemory", "()J");
0N/A max = callLongMethod(env, runtime, maxMemory);
0N/A } END_WITH_LOCAL_REFS;
0N/A return max;
0N/A}
0N/A
0N/Avoid
0N/AcreateAgentThread(JNIEnv *env, const char *name, jvmtiStartFunction func)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(name!=NULL);
0N/A HPROF_ASSERT(func!=NULL);
0N/A
0N/A WITH_LOCAL_REFS(env, 1) {
0N/A jclass clazz;
0N/A jmethodID threadConstructor;
0N/A jmethodID threadSetDaemon;
0N/A jthread thread;
0N/A jstring nameString;
0N/A jthreadGroup systemThreadGroup;
0N/A jthreadGroup * groups;
0N/A jint groupCount;
0N/A
0N/A thread = NULL;
0N/A systemThreadGroup = NULL;
0N/A groups = NULL;
0N/A clazz = class_get_class(env, gdata->thread_cnum);
0N/A HPROF_ASSERT(clazz!=NULL);
0N/A threadConstructor = getMethodID(env, clazz, "<init>",
0N/A "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
0N/A threadSetDaemon = getMethodID(env, clazz, "setDaemon",
0N/A "(Z)V");
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetTopThreadGroups)
0N/A (gdata->jvmti, &groupCount, &groups);
0N/A if ( error == JVMTI_ERROR_NONE ) {
0N/A if ( groupCount > 0 ) {
0N/A systemThreadGroup = groups[0];
0N/A }
0N/A jvmtiDeallocate(groups);
0N/A
0N/A nameString = newStringUTF(env, name);
0N/A HPROF_ASSERT(nameString!=NULL);
0N/A thread = newThreadObject(env, clazz, threadConstructor,
0N/A systemThreadGroup, nameString);
0N/A HPROF_ASSERT(thread!=NULL);
0N/A callVoidMethod(env, thread, threadSetDaemon, JNI_TRUE);
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,RunAgentThread)
0N/A (gdata->jvmti, thread, func, NULL, JVMTI_THREAD_MAX_PRIORITY);
0N/A
0N/A /* After the thread is running... */
0N/A
0N/A /* Make sure the TLS table has this thread as an agent thread */
0N/A tls_agent_thread(env, thread);
0N/A }
0N/A } END_WITH_LOCAL_REFS;
0N/A
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot create agent thread");
0N/A }
0N/A}
0N/A
0N/Ajlong
0N/AgetThreadCpuTime(jthread thread)
0N/A{
0N/A jvmtiError error;
0N/A jlong cpuTime;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A cpuTime = -1;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadCpuTime)
0N/A (gdata->jvmti, thread, &cpuTime);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get cpu time");
0N/A }
0N/A return cpuTime;
0N/A}
0N/A
0N/A/* Get frame count */
0N/Avoid
0N/AgetFrameCount(jthread thread, jint *pcount)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A HPROF_ASSERT(pcount!=NULL);
0N/A *pcount = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
0N/A (gdata->jvmti, thread, pcount);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A *pcount = 0;
0N/A }
0N/A}
0N/A
0N/A/* Get call trace */
0N/Avoid
0N/AgetStackTrace(jthread thread, jvmtiFrameInfo *pframes, jint depth, jint *pcount)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(thread!=NULL);
0N/A HPROF_ASSERT(pframes!=NULL);
0N/A HPROF_ASSERT(depth >= 0);
0N/A HPROF_ASSERT(pcount!=NULL);
0N/A *pcount = 0;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetStackTrace)
0N/A (gdata->jvmti, thread, 0, depth, pframes, pcount);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A *pcount = 0;
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AgetThreadListStackTraces(jint count, jthread *threads,
0N/A jint depth, jvmtiStackInfo **stack_info)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A HPROF_ASSERT(threads!=NULL);
0N/A HPROF_ASSERT(stack_info!=NULL);
0N/A HPROF_ASSERT(depth >= 0);
0N/A HPROF_ASSERT(count > 0);
0N/A *stack_info = NULL;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadListStackTraces)
0N/A (gdata->jvmti, count, threads, depth, stack_info);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot get thread list stack info");
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AfollowReferences(jvmtiHeapCallbacks *pHeapCallbacks, void *user_data)
0N/A{
0N/A jvmtiError error;
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,FollowReferences)
0N/A (gdata->jvmti, 0, NULL, NULL, pHeapCallbacks, user_data);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot follow references");
0N/A }
0N/A}
0N/A
0N/A/* GC control */
0N/Avoid
0N/ArunGC(void)
0N/A{
0N/A jvmtiError error;
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,ForceGarbageCollection)
0N/A (gdata->jvmti);
0N/A if ( error != JVMTI_ERROR_NONE ) {
0N/A HPROF_JVMTI_ERROR(error, "Cannot force garbage collection");
0N/A }
0N/A}
0N/A
0N/A/* ------------------------------------------------------------------- */
0N/A/* Getting the initial JVMTI environment */
0N/A
0N/Avoid
0N/AgetJvmti(void)
0N/A{
0N/A jvmtiEnv *jvmti = NULL;
0N/A jint res;
0N/A jint jvmtiCompileTimeMajorVersion;
0N/A jint jvmtiCompileTimeMinorVersion;
0N/A jint jvmtiCompileTimeMicroVersion;
0N/A
0N/A res = JVM_FUNC_PTR(gdata->jvm,GetEnv)
0N/A (gdata->jvm, (void **)&jvmti, JVMTI_VERSION_1);
0N/A if (res != JNI_OK) {
0N/A char buf[256];
0N/A
0N/A (void)md_snprintf(buf, sizeof(buf),
0N/A "Unable to access JVMTI Version 1 (0x%x),"
0N/A " is your JDK a 5.0 or newer version?"
0N/A " JNIEnv's GetEnv() returned %d",
0N/A JVMTI_VERSION_1, res);
0N/A buf[sizeof(buf)-1] = 0;
0N/A HPROF_ERROR(JNI_FALSE, buf);
0N/A error_exit_process(1); /* Kill entire process, no core dump */
0N/A }
0N/A gdata->jvmti = jvmti;
0N/A
0N/A /* Check to make sure the version of jvmti.h we compiled with
0N/A * matches the runtime version we are using.
0N/A */
0N/A jvmtiCompileTimeMajorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR )
0N/A >> JVMTI_VERSION_SHIFT_MAJOR;
0N/A jvmtiCompileTimeMinorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR )
0N/A >> JVMTI_VERSION_SHIFT_MINOR;
0N/A jvmtiCompileTimeMicroVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO )
0N/A >> JVMTI_VERSION_SHIFT_MICRO;
0N/A if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(),
0N/A jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) {
0N/A char buf[256];
0N/A
0N/A (void)md_snprintf(buf, sizeof(buf),
0N/A "This " AGENTNAME " native library will not work with this VM's "
0N/A "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d]."
0N/A ,
0N/A jvmtiMajorVersion(),
0N/A jvmtiMinorVersion(),
0N/A jvmtiMicroVersion(),
0N/A jvmtiCompileTimeMajorVersion,
0N/A jvmtiCompileTimeMinorVersion,
0N/A jvmtiCompileTimeMicroVersion);
0N/A buf[sizeof(buf)-1] = 0;
0N/A HPROF_ERROR(JNI_FALSE, buf);
0N/A error_exit_process(1); /* Kill entire process, no core dump wanted */
0N/A }
0N/A}