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