1 /* 2 * Copyright (c) 2014, 2018, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 #include <jni.h> 24 #include <stdio.h> 25 26 #include <string.h> 27 #include <jvmti.h> 28 29 #define STATUS_FAILED 2 30 #define STATUS_PASSED 0 31 32 #define REFERENCES_ARRAY_SIZE 10000000 33 34 #ifndef JNI_ENV_ARG 35 36 #ifdef __cplusplus 37 #define JNI_ENV_ARG(x, y) x 38 #define JNI_ENV_PTR(x) x 39 #else 40 #define JNI_ENV_ARG(x, y) x , y 41 #define JNI_ENV_PTR(x) (*x) 42 #endif 43 44 #endif 45 46 #ifndef _Included_gc_g1_unloading_unloading_classloaders_JNIClassloader 47 #define _Included_gc_g1_unloading_unloading_classloaders_JNIClassloader 48 49 #ifdef __cplusplus 50 extern "C" { 51 #endif 52 53 /* 54 * Class: gc_g1_unloading_unloading_classloaders_JNIClassloader 55 * Method: loadThroughJNI0 56 * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;[B)Ljava/lang/Class; 57 */ 58 JNIEXPORT jclass JNICALL Java_gc_g1_unloading_classloaders_JNIClassloader_loadThroughJNI0 (JNIEnv * env, 59 jclass clazz, jstring className, jobject classLoader, jbyteArray bytecode) { 60 61 const char * classNameChar = JNI_ENV_PTR(env)->GetStringUTFChars(JNI_ENV_ARG(env, className), NULL); 62 jbyte * arrayContent = JNI_ENV_PTR(env)->GetByteArrayElements(JNI_ENV_ARG(env, bytecode), NULL); 63 jsize bytecodeLength = JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG(env, bytecode)); 64 jclass returnValue = JNI_ENV_PTR(env)->DefineClass(JNI_ENV_ARG(env, classNameChar), classLoader, arrayContent, bytecodeLength); 65 if (!returnValue) { 66 printf("ERROR: DefineClass call returned NULL by some reason. Classloading failed.\n"); 67 } 68 69 return returnValue; 70 } 71 72 /* 73 * Class: gc_g1_unloading_unloading_loading_ClassLoadingThread 74 * Method: makeRedefinition0 75 * Signature: (ILjava/lang/Class;[B)I 76 */ 77 JNIEXPORT jint JNICALL Java_gc_g1_unloading_loading_ClassLoadingThread_makeRedefinition0(JNIEnv *env, 78 jclass cls, jint fl, jclass redefCls, jbyteArray classBytes) { 79 JavaVM * jvm; 80 jvmtiEnv * jvmti; 81 jvmtiError err; 82 jvmtiCapabilities caps; 83 jvmtiClassDefinition classDef; 84 jint jint_err = JNI_ENV_PTR(env)->GetJavaVM(JNI_ENV_ARG(env, &jvm)); 85 if (jint_err) { 86 printf("GetJavaVM returned nonzero: %d", jint_err); 87 return STATUS_FAILED; 88 } 89 90 jint_err = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **)&jvmti), JVMTI_VERSION_1_0); 91 if (jint_err) { 92 printf("GetEnv returned nonzero: %d", jint_err); 93 return STATUS_FAILED; 94 } 95 96 err = JNI_ENV_PTR(jvmti)->GetPotentialCapabilities(JNI_ENV_ARG(jvmti, &caps)); 97 if (err != JVMTI_ERROR_NONE) { 98 printf("(GetPotentialCapabilities) unexpected error: %d\n",err); 99 return JNI_ERR; 100 } 101 102 err = JNI_ENV_PTR(jvmti)->AddCapabilities(JNI_ENV_ARG(jvmti, &caps)); 103 if (err != JVMTI_ERROR_NONE) { 104 printf("(AddCapabilities) unexpected error: %d\n", err); 105 return JNI_ERR; 106 } 107 108 if (!caps.can_redefine_classes) { 109 printf("ERROR: Can't redefine classes. jvmtiCapabilities.can_redefine_classes isn't set up."); 110 return STATUS_FAILED; 111 } 112 113 classDef.klass = redefCls; 114 classDef.class_byte_count = 115 JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG(env, classBytes)); 116 classDef.class_bytes = (unsigned char *) 117 JNI_ENV_PTR(env)->GetByteArrayElements(JNI_ENV_ARG(env, classBytes), 118 NULL); 119 120 if (fl == 2) { 121 printf(">>>>>>>> Invoke RedefineClasses():\n"); 122 printf("\tnew class byte count=%d\n", classDef.class_byte_count); 123 } 124 err = JNI_ENV_PTR(jvmti)->RedefineClasses(JNI_ENV_ARG(jvmti, 1), &classDef); 125 if (err != JVMTI_ERROR_NONE) { 126 printf("%s: Failed to call RedefineClasses():\n", __FILE__); 127 printf("\tthe function returned error %d\n", err); 128 printf("\tFor more info about this error see the JVMTI spec.\n"); 129 return STATUS_FAILED; 130 } 131 if (fl == 2) 132 printf("<<<<<<<< RedefineClasses() is successfully done\n"); 133 134 return STATUS_PASSED; 135 } 136 137 jobject referencesArray[REFERENCES_ARRAY_SIZE]; 138 int firstFreeIndex = 0; 139 140 /* 141 * Class: gc_g1_unloading_unloading_keepref_JNIGlobalRefHolder 142 * Method: keepGlobalJNIReference 143 * Signature: (Ljava/lang/Object;)I 144 */ 145 JNIEXPORT jint JNICALL Java_gc_g1_unloading_keepref_JNIGlobalRefHolder_keepGlobalJNIReference 146 (JNIEnv * env, jclass clazz, jobject obj) { 147 int returnValue; 148 referencesArray[firstFreeIndex] = JNI_ENV_PTR(env)->NewGlobalRef(JNI_ENV_ARG(env, obj)); 149 printf("checkpoint1 %d \n", firstFreeIndex); 150 returnValue = firstFreeIndex; 151 firstFreeIndex++; 152 return returnValue; 153 } 154 155 /* 156 * Class: gc_g1_unloading_unloading_keepref_JNIGlobalRefHolder 157 * Method: deleteGlobalJNIReference 158 * Signature: (I)V 159 */ 160 JNIEXPORT void JNICALL Java_gc_g1_unloading_keepref_JNIGlobalRefHolder_deleteGlobalJNIReference 161 (JNIEnv * env, jclass clazz, jint index) { 162 JNI_ENV_PTR(env)->DeleteGlobalRef(JNI_ENV_ARG(env, referencesArray[index])); 163 } 164 165 166 /* 167 * Class: gc_g1_unloading_unloading_keepref_JNILocalRefHolder 168 * Method: holdWithJNILocalReference 169 * Signature: (Ljava/lang/Object;)V 170 */ 171 JNIEXPORT void JNICALL Java_gc_g1_unloading_keepref_JNILocalRefHolder_holdWithJNILocalReference 172 (JNIEnv * env, jobject thisObject, jobject syncObject) { 173 jclass clazz, objectClazz; 174 jfieldID objectToKeepField; 175 jobject objectToKeep, localRef; 176 jmethodID waitMethod; 177 178 clazz = (*env)->GetObjectClass(env, thisObject); 179 objectToKeepField = (*env)->GetFieldID(env, clazz, "objectToKeep", "Ljava/lang/Object;"); 180 objectToKeep = (*env)->GetObjectField(env, thisObject, objectToKeepField); 181 localRef = (*env)->NewLocalRef(env, objectToKeep); 182 (*env)->SetObjectField(env, thisObject, objectToKeepField, NULL); 183 184 objectClazz = (*env)->FindClass(env, "Ljava/lang/Object;"); 185 waitMethod = (*env)->GetMethodID(env, objectClazz, "wait", "()V"); 186 (*env)->CallVoidMethod(env, syncObject, waitMethod); 187 printf("checkpoint2 \n"); 188 } 189 190 191 #ifdef __cplusplus 192 } 193 #endif 194 #endif