jdk/src/jdk.runtime/share/native/libjsdt/JVM.c
changeset 29262 1698800c8606
parent 29261 ea6e20f98dfa
parent 29099 766801b4d95d
child 29263 66e30e926405
child 29505 682be03b8f41
equal deleted inserted replaced
29261:ea6e20f98dfa 29262:1698800c8606
     1 /*
       
     2  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include <stdlib.h>
       
    27 
       
    28 #include "jvm.h"
       
    29 #include "jni.h"
       
    30 #include "jni_util.h"
       
    31 
       
    32 #include "jvm_symbols.h"
       
    33 #include "sun_tracing_dtrace_JVM.h"
       
    34 
       
    35 #ifdef __cplusplus
       
    36 extern "C" {
       
    37 #endif
       
    38 
       
    39 static JvmSymbols* jvm_symbols = NULL;
       
    40 
       
    41 static void initialize() {
       
    42     static int initialized = 0;
       
    43     if (initialized == 0) {
       
    44         jvm_symbols = lookupJvmSymbols();
       
    45         initialized = 1;
       
    46     }
       
    47 }
       
    48 
       
    49 /*
       
    50  * Class:     sun_tracing_dtrace_JVM
       
    51  * Method:    isSupported0
       
    52  * Signature: ()I
       
    53  */
       
    54 JNIEXPORT jboolean JNICALL Java_sun_tracing_dtrace_JVM_isSupported0(
       
    55         JNIEnv* env, jclass cls) {
       
    56     initialize();
       
    57     if (jvm_symbols != NULL) {
       
    58         return jvm_symbols->IsSupported(env) ? JNI_TRUE : JNI_FALSE;
       
    59     } else {
       
    60         return JNI_FALSE;
       
    61     }
       
    62 }
       
    63 
       
    64 // Macros that cause an immediate return if we detect an exception
       
    65 #define CHECK if ((*env)->ExceptionOccurred(env)) { return; }
       
    66 #define CHECK_(x) if ((*env)->ExceptionOccurred(env)) { return x; }
       
    67 
       
    68 static void readProbeData (
       
    69         JNIEnv* env, jobject probe, JVM_DTraceProbe* jvm_probe) {
       
    70     jclass clazz;
       
    71     jmethodID mid;
       
    72     jobject method;
       
    73 
       
    74     if (jvm_probe == NULL) {
       
    75         return; // just in case
       
    76     }
       
    77 
       
    78     clazz = (*env)->GetObjectClass(env, probe); CHECK
       
    79 
       
    80     mid = (*env)->GetMethodID(
       
    81         env, clazz, "getFunctionName", "()Ljava/lang/String;"); CHECK
       
    82     jvm_probe->function = (jstring)(*env)->CallObjectMethod(
       
    83         env, probe, mid); CHECK
       
    84 
       
    85     mid = (*env)->GetMethodID(
       
    86         env, clazz, "getProbeName", "()Ljava/lang/String;"); CHECK
       
    87     jvm_probe->name = (jstring)(*env)->CallObjectMethod(env, probe, mid); CHECK
       
    88 
       
    89     mid = (*env)->GetMethodID(
       
    90         env, clazz, "getMethod", "()Ljava/lang/reflect/Method;"); CHECK
       
    91     method = (*env)->CallObjectMethod(env, probe, mid); CHECK
       
    92     jvm_probe->method = (*env)->FromReflectedMethod(env, method); CHECK
       
    93 }
       
    94 
       
    95 static void readFieldInterfaceAttributes(
       
    96         char* annotationName, JNIEnv* env, jobject provider,
       
    97         JVM_DTraceInterfaceAttributes* attrs) {
       
    98     jobject result;
       
    99     jobject result_clazz;
       
   100     jclass provider_clazz;
       
   101     jclass annotation_clazz;
       
   102     jmethodID get;
       
   103     jmethodID enc;
       
   104 
       
   105     provider_clazz = (*env)->GetObjectClass(env, provider); CHECK
       
   106     annotation_clazz = (*env)->FindClass(env, annotationName); CHECK
       
   107 
       
   108     get = (*env)->GetMethodID(env, provider_clazz, "getNameStabilityFor",
       
   109         "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/StabilityLevel;"); CHECK
       
   110     result = (*env)->CallObjectMethod(
       
   111         env, provider, get, annotation_clazz); CHECK
       
   112     result_clazz = (*env)->GetObjectClass(env, result); CHECK
       
   113     enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK
       
   114     attrs->nameStability = (*env)->CallIntMethod(env, result, enc); CHECK
       
   115 
       
   116     get = (*env)->GetMethodID(env, provider_clazz, "getDataStabilityFor",
       
   117         "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/StabilityLevel;"); CHECK
       
   118     result = (*env)->CallObjectMethod(
       
   119         env, provider, get, annotation_clazz); CHECK
       
   120     result_clazz = (*env)->GetObjectClass(env, result); CHECK
       
   121     enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK
       
   122     attrs->dataStability = (*env)->CallIntMethod(env, result, enc); CHECK
       
   123 
       
   124     get = (*env)->GetMethodID(env, provider_clazz, "getDependencyClassFor",
       
   125         "(Ljava/lang/Class;)Lcom/sun/tracing/dtrace/DependencyClass;"); CHECK
       
   126     result = (*env)->CallObjectMethod(
       
   127         env, provider, get, annotation_clazz); CHECK
       
   128     result_clazz = (*env)->GetObjectClass(env, result); CHECK
       
   129     enc = (*env)->GetMethodID(env, result_clazz, "getEncoding", "()I"); CHECK
       
   130     attrs->dependencyClass = (*env)->CallIntMethod(env, result, enc); CHECK
       
   131 }
       
   132 
       
   133 static void readInterfaceAttributes(
       
   134         JNIEnv* env, jobject provider, JVM_DTraceProvider* jvm_provider) {
       
   135     readFieldInterfaceAttributes("com/sun/tracing/dtrace/ProviderAttributes",
       
   136         env, provider, &(jvm_provider->providerAttributes));
       
   137     readFieldInterfaceAttributes("com/sun/tracing/dtrace/ModuleAttributes",
       
   138         env, provider, &(jvm_provider->moduleAttributes));
       
   139     readFieldInterfaceAttributes("com/sun/tracing/dtrace/FunctionAttributes",
       
   140         env, provider, &(jvm_provider->functionAttributes));
       
   141     readFieldInterfaceAttributes("com/sun/tracing/dtrace/NameAttributes",
       
   142         env, provider, &(jvm_provider->nameAttributes));
       
   143     readFieldInterfaceAttributes("com/sun/tracing/dtrace/ArgsAttributes",
       
   144         env, provider, &(jvm_provider->argsAttributes));
       
   145 }
       
   146 
       
   147 static int readProviderData(
       
   148         JNIEnv* env, jobject provider, JVM_DTraceProvider* jvm_provider) {
       
   149     jmethodID mid;
       
   150     jobjectArray probes;
       
   151     jsize i;
       
   152     jclass clazz = (*env)->GetObjectClass(env, provider); CHECK_(0)
       
   153     mid = (*env)->GetMethodID(
       
   154         env, clazz, "getProbes", "()[Lsun/tracing/dtrace/DTraceProbe;"); CHECK_(0)
       
   155     probes = (jobjectArray)(*env)->CallObjectMethod(
       
   156         env, provider, mid); CHECK_(0)
       
   157 
       
   158     // Fill JVM structure, describing provider
       
   159     jvm_provider->probe_count = (*env)->GetArrayLength(env, probes); CHECK_(0)
       
   160     jvm_provider->probes = (JVM_DTraceProbe*)calloc(
       
   161         jvm_provider->probe_count, sizeof(*jvm_provider->probes));
       
   162     mid = (*env)->GetMethodID(
       
   163         env, clazz, "getProviderName", "()Ljava/lang/String;"); CHECK_(0)
       
   164     jvm_provider->name = (jstring)(*env)->CallObjectMethod(
       
   165         env, provider, mid); CHECK_(0)
       
   166 
       
   167     readInterfaceAttributes(env, provider, jvm_provider); CHECK_(0)
       
   168 
       
   169     for (i = 0; i < jvm_provider->probe_count; ++i) {
       
   170         jobject probe = (*env)->GetObjectArrayElement(env, probes, i); CHECK_(0)
       
   171         readProbeData(env, probe, &jvm_provider->probes[i]); CHECK_(0)
       
   172     }
       
   173 
       
   174     return 1;
       
   175 }
       
   176 
       
   177 /*
       
   178  * Class:     sun_tracing_dtrace_JVM
       
   179  * Method:    activate0
       
   180  * Signature: ()J
       
   181  */
       
   182 JNIEXPORT jlong JNICALL Java_sun_tracing_dtrace_JVM_activate0(
       
   183         JNIEnv* env, jclass cls, jstring moduleName, jobjectArray providers) {
       
   184     jlong handle = 0;
       
   185     jsize num_providers;
       
   186     jsize i;
       
   187     jsize count = 0;
       
   188     JVM_DTraceProvider* jvm_providers;
       
   189 
       
   190     initialize();
       
   191 
       
   192     if (jvm_symbols == NULL) {
       
   193       return 0;
       
   194     }
       
   195 
       
   196     num_providers = (*env)->GetArrayLength(env, providers); CHECK_(0L)
       
   197 
       
   198     jvm_providers = (JVM_DTraceProvider*)calloc(
       
   199         num_providers, sizeof(*jvm_providers));
       
   200 
       
   201     for (; count < num_providers; ++count) {
       
   202         JVM_DTraceProvider* p = &(jvm_providers[count]);
       
   203         jobject provider = (*env)->GetObjectArrayElement(
       
   204             env, providers, count);
       
   205         if ((*env)->ExceptionOccurred(env) ||
       
   206             ! readProviderData(env, provider, p)) {
       
   207             // got an error, bail out!
       
   208             break;
       
   209         }
       
   210     }
       
   211 
       
   212     if (count == num_providers) {
       
   213         // all providers successfully loaded - get the handle
       
   214         handle = jvm_symbols->Activate(
       
   215             env, JVM_TRACING_DTRACE_VERSION, moduleName,
       
   216             num_providers, jvm_providers);
       
   217     }
       
   218 
       
   219     for (i = 0; i < num_providers; ++i) {
       
   220         JVM_DTraceProvider* p = &(jvm_providers[i]);
       
   221         free(p->probes);
       
   222     }
       
   223     free(jvm_providers);
       
   224 
       
   225     return handle;
       
   226 }
       
   227 
       
   228 /*
       
   229  * Class:     sun_tracing_dtrace_JVM
       
   230  * Method:    dispose0
       
   231  * Signature: (J)V
       
   232  */
       
   233 JNIEXPORT void JNICALL Java_sun_tracing_dtrace_JVM_dispose0(
       
   234         JNIEnv* env, jclass cls, jlong handle) {
       
   235     if (jvm_symbols != NULL && handle != 0) {
       
   236         jvm_symbols->Dispose(env, handle);
       
   237     }
       
   238 }
       
   239 
       
   240 /*
       
   241  * Class:     sun_tracing_dtrace_JVM
       
   242  * Method:    isEnabled0
       
   243  * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
       
   244  */
       
   245 JNIEXPORT jboolean JNICALL Java_sun_tracing_dtrace_JVM_isEnabled0(
       
   246         JNIEnv* env, jclass cls, jobject method) {
       
   247     jmethodID mid;
       
   248     if (jvm_symbols != NULL && method != NULL) {
       
   249         mid = (*env)->FromReflectedMethod(env, method);
       
   250         return jvm_symbols->IsProbeEnabled(env, mid);
       
   251     }
       
   252     return JNI_FALSE;
       
   253 }
       
   254 
       
   255 /*
       
   256  * Class:     sun_tracing_dtrace_JVM
       
   257  * Method:    defineClass0
       
   258  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class;
       
   259  *
       
   260  * The implementation of this native static method is a copy of that of
       
   261  * the native instance method Java_java_lang_ClassLoader_defineClass0()
       
   262  * with the implicit "this" parameter becoming the "loader" parameter.
       
   263  *
       
   264  * This code was cloned and modified from java_lang_reflect_Proxy
       
   265  */
       
   266 JNIEXPORT jclass JNICALL
       
   267 Java_sun_tracing_dtrace_JVM_defineClass0(
       
   268         JNIEnv *env, jclass ignore, jobject loader, jstring name, jbyteArray data,
       
   269         jint offset, jint length)
       
   270 {
       
   271     jbyte *body;
       
   272     char *utfName;
       
   273     jclass result = 0;
       
   274     char buf[128];
       
   275 
       
   276     if (data == NULL) {
       
   277         return 0;
       
   278     }
       
   279 
       
   280     /* Work around 4153825. malloc crashes on Solaris when passed a
       
   281      * negative size.
       
   282      */
       
   283     if (length < 0) {
       
   284         return 0;
       
   285     }
       
   286 
       
   287     body = (jbyte *)malloc(length);
       
   288 
       
   289     if (body == 0) {
       
   290         return 0;
       
   291     }
       
   292 
       
   293     (*env)->GetByteArrayRegion(env, data, offset, length, body);
       
   294 
       
   295     if ((*env)->ExceptionOccurred(env))
       
   296         goto free_body;
       
   297 
       
   298     if (name != NULL) {
       
   299         int i;
       
   300         jsize len = (*env)->GetStringUTFLength(env, name);
       
   301         int unicode_len = (*env)->GetStringLength(env, name);
       
   302         if (len >= (jsize)sizeof(buf)) {
       
   303             utfName = malloc(len + 1);
       
   304             if (utfName == NULL) {
       
   305                 goto free_body;
       
   306             }
       
   307         } else {
       
   308             utfName = buf;
       
   309         }
       
   310         (*env)->GetStringUTFRegion(env, name, 0, unicode_len, utfName);
       
   311 
       
   312         // Convert '.' to '/' in the package name
       
   313         for (i = 0; i < unicode_len; ++i) {
       
   314             if (utfName[i] == '.') {
       
   315                 utfName[i] = '/';
       
   316             }
       
   317         }
       
   318     } else {
       
   319         utfName = NULL;
       
   320     }
       
   321 
       
   322     result = (*env)->DefineClass(env, utfName, loader, body, length);
       
   323 
       
   324     if (utfName && utfName != buf)
       
   325         free(utfName);
       
   326 
       
   327  free_body:
       
   328     free(body);
       
   329     return result;
       
   330 }
       
   331 
       
   332 #ifdef __cplusplus
       
   333 }
       
   334 #endif