--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/tracing/dtrace/JVM.c Thu Apr 17 22:00:16 2008 -0400
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#include <stdlib.h>
+
+#include "jvm.h"
+#include "jni.h"
+#include "jni_util.h"
+
+#include "jvm_symbols.h"
+#include "sun_tracing_dtrace_JVM.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static JvmSymbols* jvm_symbols = NULL;
+
+static void initialize() {
+ static int initialized = 0;
+ if (initialized == 0) {
+ jvm_symbols = lookupJvmSymbols();
+ initialized = 1;
+ }
+}
+
+/*
+ * Class: sun_tracing_dtrace_JVM
+ * Method: isSupported0
+ * Signature: ()I
+ */
+JNIEXPORT jboolean JNICALL Java_sun_tracing_dtrace_JVM_isSupported0(
+ JNIEnv* env, jclass cls) {
+ initialize();
+ if (jvm_symbols != NULL) {
+ return jvm_symbols->IsSupported(env) ? JNI_TRUE : JNI_FALSE;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+// Macros that cause an immediate return if we detect an exception
+#define CHECK if ((*env)->ExceptionOccurred(env)) { return; }
+#define CHECK_(x) if ((*env)->ExceptionOccurred(env)) { return x; }
+
+static void readProbeData (
+ JNIEnv* env, jobject probe, JVM_DTraceProbe* jvm_probe) {
+ jclass clazz;
+ jmethodID mid;
+ jobject method;
+
+ if (jvm_probe == NULL) {
+ return; // just in case
+ }
+
+ clazz = (*env)->GetObjectClass(env, probe); CHECK
+
+ mid = (*env)->GetMethodID(
+ env, clazz, "getFunctionName", "()Ljava/lang/String;"); CHECK
+ jvm_probe->function = (jstring)(*env)->CallObjectMethod(
+ env, probe, mid); CHECK
+
+ mid = (*env)->GetMethodID(
+ env, clazz, "getProbeName", "()Ljava/lang/String;"); CHECK
+ jvm_probe->name = (jstring)(*env)->CallObjectMethod(env, probe, mid); CHECK
+
+ mid = (*env)->GetMethodID(
+ env, clazz, "getMethod", "()Ljava/lang/reflect/Method;"); CHECK
+ method = (*env)->CallObjectMethod(env, probe, mid); CHECK
+ jvm_probe->method = (*env)->FromReflectedMethod(env, method); CHECK
+}
+
+static void readFieldInterfaceAttributes(
+ char* annotationName, JNIEnv* env, jobject provider,
+ JVM_DTraceInterfaceAttributes* attrs) {
+ jobject result;
+ jobject result_clazz;
+ jclass provider_clazz;
+ jclass annotation_clazz;
+ jmethodID get;
+ jmethodID enc;
+
+ provider_clazz = (*env)->GetObjectClass(env, provider); CHECK
+ annotation_clazz = (*env)->FindClass(env, annotationName); CHECK
+
+ get = (*env)->GetMethodID(env, provider_clazz, "getNameStabilityFor",
+ "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/StabilityLevel;"); CHECK
+ result = (*env)->CallObjectMethod(
+ env, provider, get, annotation_clazz); CHECK
+ result_clazz = (*env)->GetObjectClass(env, result); CHECK
+ enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK
+ attrs->nameStability = (*env)->CallIntMethod(env, result, enc); CHECK
+
+ get = (*env)->GetMethodID(env, provider_clazz, "getDataStabilityFor",
+ "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/StabilityLevel;"); CHECK
+ result = (*env)->CallObjectMethod(
+ env, provider, get, annotation_clazz); CHECK
+ result_clazz = (*env)->GetObjectClass(env, result); CHECK
+ enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK
+ attrs->dataStability = (*env)->CallIntMethod(env, result, enc); CHECK
+
+ get = (*env)->GetMethodID(env, provider_clazz, "getDependencyClassFor",
+ "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/DependencyClass;"); CHECK
+ result = (*env)->CallObjectMethod(
+ env, provider, get, annotation_clazz); CHECK
+ result_clazz = (*env)->GetObjectClass(env, result); CHECK
+ enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK
+ attrs->dependencyClass = (*env)->CallIntMethod(env, result, enc); CHECK
+}
+
+static void readInterfaceAttributes(
+ JNIEnv* env, jobject provider, JVM_DTraceProvider* jvm_provider) {
+ readFieldInterfaceAttributes("com/sun/tracing/dtrace/ProviderAttributes",
+ env, provider, &(jvm_provider->providerAttributes));
+ readFieldInterfaceAttributes("com/sun/tracing/dtrace/ModuleAttributes",
+ env, provider, &(jvm_provider->moduleAttributes));
+ readFieldInterfaceAttributes("com/sun/tracing/dtrace/FunctionAttributes",
+ env, provider, &(jvm_provider->functionAttributes));
+ readFieldInterfaceAttributes("com/sun/tracing/dtrace/NameAttributes",
+ env, provider, &(jvm_provider->nameAttributes));
+ readFieldInterfaceAttributes("com/sun/tracing/dtrace/ArgsAttributes",
+ env, provider, &(jvm_provider->argsAttributes));
+}
+
+static void readProviderData(
+ JNIEnv* env, jobject provider, JVM_DTraceProvider* jvm_provider) {
+ jmethodID mid;
+ jobjectArray probes;
+ jsize i;
+ jclass clazz = (*env)->GetObjectClass(env, provider); CHECK
+ mid = (*env)->GetMethodID(
+ env, clazz, "getProbes", "()[Lsun/tracing/dtrace/DTraceProbe;"); CHECK
+ probes = (jobjectArray)(*env)->CallObjectMethod(
+ env, provider, mid); CHECK
+
+ // Fill JVM structure, describing provider
+ jvm_provider->probe_count = (*env)->GetArrayLength(env, probes); CHECK
+ jvm_provider->probes = (JVM_DTraceProbe*)calloc(
+ jvm_provider->probe_count, sizeof(*jvm_provider->probes));
+ mid = (*env)->GetMethodID(
+ env, clazz, "getProviderName", "()Ljava/lang/String;"); CHECK
+ jvm_provider->name = (jstring)(*env)->CallObjectMethod(
+ env, provider, mid); CHECK
+
+ readInterfaceAttributes(env, provider, jvm_provider); CHECK
+
+ for (i = 0; i < jvm_provider->probe_count; ++i) {
+ jobject probe = (*env)->GetObjectArrayElement(env, probes, i); CHECK
+ readProbeData(env, probe, &jvm_provider->probes[i]); CHECK
+ }
+}
+
+/*
+ * Class: sun_tracing_dtrace_JVM
+ * Method: activate0
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_sun_tracing_dtrace_JVM_activate0(
+ JNIEnv* env, jclass cls, jstring moduleName, jobjectArray providers) {
+ jlong handle = 0;
+ jsize num_providers;
+ jsize i;
+ JVM_DTraceProvider* jvm_providers;
+
+ initialize();
+
+ if (jvm_symbols == NULL) {
+ return 0;
+ }
+
+ num_providers = (*env)->GetArrayLength(env, providers); CHECK_(0L)
+
+ jvm_providers = (JVM_DTraceProvider*)calloc(
+ num_providers, sizeof(*jvm_providers));
+
+ for (i = 0; i < num_providers; ++i) {
+ JVM_DTraceProvider* p = &(jvm_providers[i]);
+ jobject provider = (*env)->GetObjectArrayElement(
+ env, providers, i);
+ readProviderData(env, provider, p);
+ }
+
+ handle = jvm_symbols->Activate(
+ env, JVM_TRACING_DTRACE_VERSION, moduleName,
+ num_providers, jvm_providers);
+
+ for (i = 0; i < num_providers; ++i) {
+ JVM_DTraceProvider* p = &(jvm_providers[i]);
+ free(p->probes);
+ }
+ free(jvm_providers);
+
+ return handle;
+}
+
+/*
+ * Class: sun_tracing_dtrace_JVM
+ * Method: dispose0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_sun_tracing_dtrace_JVM_dispose0(
+ JNIEnv* env, jclass cls, jlong handle) {
+ if (jvm_symbols != NULL && handle != 0) {
+ jvm_symbols->Dispose(env, handle);
+ }
+}
+
+/*
+ * Class: sun_tracing_dtrace_JVM
+ * Method: isEnabled0
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_tracing_dtrace_JVM_isEnabled0(
+ JNIEnv* env, jclass cls, jobject method) {
+ jmethodID mid;
+ if (jvm_symbols != NULL && method != NULL) {
+ mid = (*env)->FromReflectedMethod(env, method);
+ return jvm_symbols->IsProbeEnabled(env, mid);
+ }
+ return JNI_FALSE;
+}
+
+/*
+ * Class: sun_tracing_dtrace_JVM
+ * Method: defineClass0
+ * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class;
+ *
+ * The implementation of this native static method is a copy of that of
+ * the native instance method Java_java_lang_ClassLoader_defineClass0()
+ * with the implicit "this" parameter becoming the "loader" parameter.
+ *
+ * This code was cloned and modified from java_lang_reflect_Proxy
+ */
+JNIEXPORT jclass JNICALL
+Java_sun_tracing_dtrace_JVM_defineClass0(
+ JNIEnv *env, jclass ignore, jobject loader, jstring name, jbyteArray data,
+ jint offset, jint length)
+{
+ jbyte *body;
+ char *utfName;
+ jclass result = 0;
+ char buf[128];
+
+ if (data == NULL) {
+ return 0;
+ }
+
+ /* Work around 4153825. malloc crashes on Solaris when passed a
+ * negative size.
+ */
+ if (length < 0) {
+ return 0;
+ }
+
+ body = (jbyte *)malloc(length);
+
+ if (body == 0) {
+ return 0;
+ }
+
+ (*env)->GetByteArrayRegion(env, data, offset, length, body);
+
+ if ((*env)->ExceptionOccurred(env))
+ goto free_body;
+
+ if (name != NULL) {
+ int i;
+ int len = (*env)->GetStringUTFLength(env, name);
+ int unicode_len = (*env)->GetStringLength(env, name);
+ if (len >= sizeof(buf)) {
+ utfName = malloc(len + 1);
+ if (utfName == NULL) {
+ goto free_body;
+ }
+ } else {
+ utfName = buf;
+ }
+ (*env)->GetStringUTFRegion(env, name, 0, unicode_len, utfName);
+
+ // Convert '.' to '/' in the package name
+ for (i = 0; i < unicode_len; ++i) {
+ if (utfName[i] == '.') {
+ utfName[i] = '/';
+ }
+ }
+ } else {
+ utfName = NULL;
+ }
+
+ result = (*env)->DefineClass(env, utfName, loader, body, length);
+
+ if (utfName && utfName != buf)
+ free(utfName);
+
+ free_body:
+ free(body);
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif