1 /* 2 * Copyright (c) 2019, 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 24 /* On AIX, unfortunately, we are not able to invoke the libjvm on the primordial thread. */ 25 #ifdef _AIX 26 #define CREATEVM_IN_NEW_THREAD 27 #else 28 #undef CREATEVM_IN_NEW_THREAD 29 #endif 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 34 #include "jni.h" 35 #include "assert.h" 36 37 #ifdef CREATEVM_IN_NEW_THREAD 38 #ifdef WIN32 39 #error Not on Windows. 40 #else 41 #include "pthread.h" 42 #endif 43 #endif 44 45 static jclass classClass; 46 static jclass iaeClass; 47 static jmethodID mid_Class_forName; 48 static jmethodID mid_Class_getField; 49 static jmethodID mid_Field_get; 50 51 int getField(JNIEnv *env, char* declaringClass_name, char* field_name); 52 int checkAndClearIllegalAccessExceptionThrown(JNIEnv *env); 53 54 static int main_inner(int argc, char** args) { 55 JavaVM *jvm; 56 JNIEnv *env; 57 JavaVMInitArgs vm_args; 58 JavaVMOption options[1]; 59 jint rc; 60 61 vm_args.version = JNI_VERSION_1_2; 62 vm_args.nOptions = 0; 63 vm_args.options = options; 64 65 if ((rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)) != JNI_OK) { 66 printf("ERROR: cannot create VM.\n"); 67 exit(-1); 68 } 69 70 classClass = (*env)->FindClass(env, "java/lang/Class"); 71 iaeClass = (*env)->FindClass(env, "java/lang/IllegalAccessException"); 72 mid_Class_forName = (*env)->GetStaticMethodID(env, classClass, "forName", 73 "(Ljava/lang/String;)Ljava/lang/Class;"); 74 assert(mid_Class_forName != NULL); 75 76 mid_Class_getField = (*env)->GetMethodID(env, classClass, "getField", 77 "(Ljava/lang/String;)Ljava/lang/reflect/Field;"); 78 assert(mid_Class_getField != NULL); 79 80 jclass fieldClass = (*env)->FindClass(env, "java/lang/reflect/Field"); 81 mid_Field_get = (*env)->GetMethodID(env, fieldClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); 82 assert(mid_Class_getField != NULL); 83 84 // can access to public member of an exported type 85 if ((rc = getField(env, "java.lang.Integer", "TYPE")) != 0) { 86 printf("ERROR: fail to access java.lang.Integer::TYPE\n"); 87 exit(-1); 88 } 89 90 // expect IAE to jdk.internal.misc.Unsafe class 91 if ((rc = getField(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET")) == 0) { 92 printf("ERROR: IAE not thrown\n"); 93 exit(-1); 94 } 95 if (checkAndClearIllegalAccessExceptionThrown(env) != JNI_TRUE) { 96 printf("ERROR: exception is not an instance of IAE\n"); 97 exit(-1); 98 } 99 100 // expect IAE to jdk.internal.misc.Unsafe class 101 if ((rc = getField(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET")) == 0) { 102 printf("ERROR: IAE not thrown\n"); 103 exit(-1); 104 } 105 if (checkAndClearIllegalAccessExceptionThrown(env) != JNI_TRUE) { 106 printf("ERROR: exception is not an instance of IAE\n"); 107 exit(-1); 108 } 109 110 (*jvm)->DestroyJavaVM(jvm); 111 return 0; 112 } 113 114 int checkAndClearIllegalAccessExceptionThrown(JNIEnv *env) { 115 jthrowable t = (*env)->ExceptionOccurred(env); 116 if ((*env)->IsInstanceOf(env, t, iaeClass) == JNI_TRUE) { 117 (*env)->ExceptionClear(env); 118 return JNI_TRUE; 119 } 120 return JNI_FALSE; 121 } 122 123 int getField(JNIEnv *env, char* declaringClass_name, char* field_name) { 124 jobject c = (*env)->CallStaticObjectMethod(env, classClass, mid_Class_forName, 125 (*env)->NewStringUTF(env, declaringClass_name)); 126 if ((*env)->ExceptionOccurred(env) != NULL) { 127 (*env)->ExceptionDescribe(env); 128 return 1; 129 } 130 131 jobject f = (*env)->CallObjectMethod(env, c, mid_Class_getField, (*env)->NewStringUTF(env, field_name)); 132 if ((*env)->ExceptionOccurred(env) != NULL) { 133 (*env)->ExceptionDescribe(env); 134 return 2; 135 } 136 137 jobject v = (*env)->CallObjectMethod(env, f, mid_Field_get, c); 138 if ((*env)->ExceptionOccurred(env) != NULL) { 139 (*env)->ExceptionDescribe(env); 140 return 3; 141 } 142 return 0; 143 } 144 145 146 #ifdef CREATEVM_IN_NEW_THREAD 147 148 struct args_t { 149 int argc; char** argv; 150 }; 151 152 #define STACK_SIZE 0x200000 153 154 static void* thread_wrapper(void* p) { 155 const struct args_t* const p_args = (const struct args_t*) p; 156 main_inner(p_args->argc, p_args->argv); 157 return 0; 158 } 159 160 static void run_in_new_thread(const struct args_t* args) { 161 pthread_t tid; 162 pthread_attr_t attr; 163 164 pthread_attr_init(&attr); 165 pthread_attr_setstacksize(&attr, STACK_SIZE); 166 167 if (pthread_create(&tid, &attr, thread_wrapper, (void*)args) != 0) { 168 fprintf(stderr, "Failed to create main thread\n"); 169 exit(2); 170 } 171 172 if (pthread_join(tid, NULL) != 0) { 173 fprintf(stderr, "Failed to join main thread\n"); 174 exit(2); 175 } 176 } 177 178 int main(int argc, char** args) { 179 struct args_t a; 180 a.argc = argc; 181 a.argv = args; 182 run_in_new_thread(&a); 183 } 184 185 #else 186 187 int main(int argc, char** args) { 188 main_inner(argc, args); 189 } 190 191 #endif /* CREATEVM_IN_NEW_THREAD */