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 #include <stdio.h>
  25 #include <stdlib.h>
  26 
  27 #include "jni.h"
  28 #include "assert.h"
  29 
  30 static jclass    classClass;
  31 static jclass    iaeClass;
  32 static jmethodID mid_Class_forName;
  33 static jmethodID mid_Class_getField;
  34 static jmethodID mid_Field_get;
  35 
  36 int getField(JNIEnv *env, char* declaringClass_name, char* field_name);
  37 int checkAndClearIllegalAccessExceptionThrown(JNIEnv *env);
  38 
  39 int main(int argc, char** args) {
  40     JavaVM *jvm;
  41     JNIEnv *env;
  42     JavaVMInitArgs vm_args;
  43     JavaVMOption options[1];
  44     jint rc;
  45 
  46     vm_args.version = JNI_VERSION_1_2;
  47     vm_args.nOptions = 0;
  48     vm_args.options = options;
  49 
  50     if ((rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)) != JNI_OK) {
  51         printf("ERROR: cannot create VM.\n");
  52         exit(-1);
  53     }
  54 
  55     classClass = (*env)->FindClass(env, "java/lang/Class");
  56     iaeClass = (*env)->FindClass(env, "java/lang/IllegalAccessException");
  57     mid_Class_forName = (*env)->GetStaticMethodID(env, classClass, "forName",
  58                                                   "(Ljava/lang/String;)Ljava/lang/Class;");
  59     assert(mid_Class_forName != NULL);
  60 
  61     mid_Class_getField = (*env)->GetMethodID(env, classClass, "getField",
  62                                              "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
  63     assert(mid_Class_getField != NULL);
  64 
  65     jclass fieldClass = (*env)->FindClass(env, "java/lang/reflect/Field");
  66     mid_Field_get = (*env)->GetMethodID(env, fieldClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
  67     assert(mid_Class_getField != NULL);
  68 
  69     // can access to public member of an exported type
  70     if ((rc = getField(env, "java.lang.Integer", "TYPE")) != 0) {
  71         printf("ERROR: fail to access java.lang.Integer::TYPE\n");
  72         exit(-1);
  73     }
  74 
  75     // expect IAE to jdk.internal.misc.Unsafe class
  76     if ((rc = getField(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET")) == 0) {
  77         printf("ERROR: IAE not thrown\n");
  78         exit(-1);
  79     }
  80     if (checkAndClearIllegalAccessExceptionThrown(env) != JNI_TRUE) {
  81         printf("ERROR: exception is not an instance of IAE\n");
  82         exit(-1);
  83     }
  84 
  85     // expect IAE to jdk.internal.misc.Unsafe class
  86     if ((rc = getField(env, "jdk.internal.misc.Unsafe", "INVALID_FIELD_OFFSET")) == 0) {
  87         printf("ERROR: IAE not thrown\n");
  88         exit(-1);
  89     }
  90     if (checkAndClearIllegalAccessExceptionThrown(env) != JNI_TRUE) {
  91         printf("ERROR: exception is not an instance of IAE\n");
  92         exit(-1);
  93     }
  94 
  95     (*jvm)->DestroyJavaVM(jvm);
  96     return 0;
  97 }
  98 
  99 int checkAndClearIllegalAccessExceptionThrown(JNIEnv *env) {
 100     jthrowable t = (*env)->ExceptionOccurred(env);
 101     if ((*env)->IsInstanceOf(env, t, iaeClass) == JNI_TRUE) {
 102         (*env)->ExceptionClear(env);
 103         return JNI_TRUE;
 104     }
 105     return JNI_FALSE;
 106 }
 107 
 108 int getField(JNIEnv *env, char* declaringClass_name, char* field_name) {
 109     jobject c = (*env)->CallStaticObjectMethod(env, classClass, mid_Class_forName,
 110                                                (*env)->NewStringUTF(env, declaringClass_name));
 111     if ((*env)->ExceptionOccurred(env) != NULL) {
 112         (*env)->ExceptionDescribe(env);
 113         return 1;
 114     }
 115 
 116     jobject f = (*env)->CallObjectMethod(env, c, mid_Class_getField, (*env)->NewStringUTF(env, field_name));
 117     if ((*env)->ExceptionOccurred(env) != NULL) {
 118         (*env)->ExceptionDescribe(env);
 119         return 2;
 120     }
 121 
 122     jobject v = (*env)->CallObjectMethod(env, f, mid_Field_get, c);
 123     if ((*env)->ExceptionOccurred(env) != NULL) {
 124         (*env)->ExceptionDescribe(env);
 125         return 3;
 126     }
 127     return 0;
 128 }
 129