1 /*
   2  * Copyright (c) 2004, 2011, 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 <string.h>
  27 
  28 #include "jni.h"
  29 #include "jni_util.h"
  30 #include "jlong.h"
  31 #include "jvm.h"
  32 #include "jdk_util.h"
  33 
  34 #include "sun_misc_VM.h"
  35 
  36 typedef jintArray (JNICALL *GET_THREAD_STATE_VALUES_FN)(JNIEnv *, jint);
  37 typedef jobjectArray (JNICALL *GET_THREAD_STATE_NAMES_FN)(JNIEnv *, jint, jintArray);
  38 
  39 static GET_THREAD_STATE_VALUES_FN GetThreadStateValues_fp = NULL;
  40 static GET_THREAD_STATE_NAMES_FN GetThreadStateNames_fp = NULL;
  41 
  42 static void get_thread_state_info(JNIEnv *env, jint state,
  43                                       jobjectArray stateValues,
  44                                       jobjectArray stateNames) {
  45     char errmsg[128];
  46     jintArray values;
  47     jobjectArray names;
  48 
  49     values = (*GetThreadStateValues_fp)(env, state);
  50     if (values == NULL) {
  51         sprintf(errmsg, "Mismatched VM version: Thread state (%d) "
  52                         "not supported", state);
  53         JNU_ThrowInternalError(env, errmsg);
  54         return;
  55     }
  56     /* state is also used as the index in the array */
  57     (*env)->SetObjectArrayElement(env, stateValues, state, values);
  58 
  59     names = (*GetThreadStateNames_fp)(env, state, values);
  60     if (names == NULL) {
  61         sprintf(errmsg, "Mismatched VM version: Thread state (%d) "
  62                         "not supported", state);
  63         JNU_ThrowInternalError(env, errmsg);
  64         return;
  65     }
  66     (*env)->SetObjectArrayElement(env, stateNames, state, names);
  67 }
  68 
  69 JNIEXPORT void JNICALL
  70 Java_sun_misc_VM_getThreadStateValues(JNIEnv *env, jclass cls,
  71                                       jobjectArray values,
  72                                       jobjectArray names)
  73 {
  74     char errmsg[128];
  75 
  76     // check if the number of Thread.State enum constants
  77     // matches the number of states defined in jvm.h
  78     jsize len1 = (*env)->GetArrayLength(env, values);
  79     jsize len2 = (*env)->GetArrayLength(env, names);
  80     if (len1 != JAVA_THREAD_STATE_COUNT || len2 != JAVA_THREAD_STATE_COUNT) {
  81         sprintf(errmsg, "Mismatched VM version: JAVA_THREAD_STATE_COUNT = %d "
  82                 " but JDK expects %d / %d",
  83                 JAVA_THREAD_STATE_COUNT, len1, len2);
  84         JNU_ThrowInternalError(env, errmsg);
  85         return;
  86     }
  87 
  88     if (GetThreadStateValues_fp == NULL) {
  89         GetThreadStateValues_fp = (GET_THREAD_STATE_VALUES_FN)
  90             JDK_FindJvmEntry("JVM_GetThreadStateValues");
  91         if (GetThreadStateValues_fp == NULL) {
  92             JNU_ThrowInternalError(env,
  93                  "Mismatched VM version: JVM_GetThreadStateValues not found");
  94             return;
  95         }
  96 
  97         GetThreadStateNames_fp = (GET_THREAD_STATE_NAMES_FN)
  98             JDK_FindJvmEntry("JVM_GetThreadStateNames");
  99         if (GetThreadStateNames_fp == NULL) {
 100             JNU_ThrowInternalError(env,
 101                  "Mismatched VM version: JVM_GetThreadStateNames not found");
 102             return ;
 103         }
 104     }
 105 
 106     get_thread_state_info(env, JAVA_THREAD_STATE_NEW, values, names);
 107     get_thread_state_info(env, JAVA_THREAD_STATE_RUNNABLE, values, names);
 108     get_thread_state_info(env, JAVA_THREAD_STATE_BLOCKED, values, names);
 109     get_thread_state_info(env, JAVA_THREAD_STATE_WAITING, values, names);
 110     get_thread_state_info(env, JAVA_THREAD_STATE_TIMED_WAITING, values, names);
 111     get_thread_state_info(env, JAVA_THREAD_STATE_TERMINATED, values, names);
 112 }
 113 
 114 JNIEXPORT jobject JNICALL
 115 Java_sun_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) {
 116     return JVM_LatestUserDefinedLoader(env);
 117 }
 118 
 119 typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t);
 120 
 121 JNIEXPORT void JNICALL
 122 Java_sun_misc_VM_initialize(JNIEnv *env, jclass cls) {
 123     GetJvmVersionInfo_fp func_p;
 124 
 125     if (!JDK_InitJvmHandle()) {
 126         JNU_ThrowInternalError(env, "Handle for JVM not found for symbol lookup");
 127         return;
 128     }
 129 
 130     func_p = (GetJvmVersionInfo_fp) JDK_FindJvmEntry("JVM_GetVersionInfo");
 131      if (func_p != NULL) {
 132         jvm_version_info info;
 133 
 134         memset(&info, 0, sizeof(info));
 135 
 136         /* obtain the JVM version info */
 137         (*func_p)(env, &info, sizeof(info));
 138     }
 139 }
 140