libAddModuleExportsAndOpensTest.c revision 12290:8953c0318163
1/* 2 * Copyright (c) 2016, 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 <string.h> 26#include "jvmti.h" 27 28#ifdef __cplusplus 29extern "C" { 30#endif 31 32#ifndef JNI_ENV_ARG 33 34#ifdef __cplusplus 35#define JNI_ENV_ARG(x, y) y 36#define JNI_ENV_PTR(x) x 37#else 38#define JNI_ENV_ARG(x,y) x, y 39#define JNI_ENV_PTR(x) (*x) 40#endif 41 42#endif 43 44#define TranslateError(err) "JVMTI error" 45 46#define PASSED 0 47#define FAILED 2 48 49static const char *EXC_CNAME = "java/lang/Exception"; 50static const char* MOD_CNAME = "Ljava/lang/reflect/Module;"; 51 52static jvmtiEnv *jvmti = NULL; 53static jint result = PASSED; 54 55static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); 56 57JNIEXPORT 58jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { 59 return Agent_Initialize(jvm, options, reserved); 60} 61 62JNIEXPORT 63jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { 64 return Agent_Initialize(jvm, options, reserved); 65} 66 67JNIEXPORT 68jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { 69 return JNI_VERSION_1_8; 70} 71 72static 73jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 74 jint res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), 75 JVMTI_VERSION_9); 76 if (res != JNI_OK || jvmti == NULL) { 77 printf(" Error: wrong result of a valid call to GetEnv!\n"); 78 return JNI_ERR; 79 } 80 81 return JNI_OK; 82} 83 84static 85jint throw_exc(JNIEnv *env, char *msg) { 86 jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); 87 88 if (exc_class == NULL) { 89 printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); 90 return -1; 91 } 92 return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); 93} 94 95static 96jclass jlrM(JNIEnv *env) { 97 jclass cls = NULL; 98 99 cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME)); 100 if (cls == NULL) { 101 printf(" Error in JNI FindClass: %s\n", MOD_CNAME); 102 } 103 return cls; 104} 105 106jmethodID 107get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) { 108 jmethodID method = NULL; 109 110 method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig); 111 if (method == NULL) { 112 printf(" Error in JNI GetMethodID %s with signature %s", name, sig); 113 } 114 return method; 115} 116 117static 118jboolean is_exported(JNIEnv *env, jobject module, const char* pkg, jboolean open) { 119 static jmethodID mIsExported = NULL; 120 jstring jstr = NULL; 121 jboolean res = JNI_FALSE; 122 123 if (mIsExported == NULL) { 124 const char* sign = "(Ljava/lang/String;)Z"; 125 const char* name = open ? "isOpen" : "isExported"; 126 mIsExported = get_method(env, jlrM(env), name, sign); 127 } 128 jstr = JNI_ENV_PTR(env)->NewStringUTF(JNI_ENV_ARG(env, pkg)); 129 res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module), 130 mIsExported, jstr); 131 return res; 132} 133 134static 135jboolean is_exported_to(JNIEnv *env, jobject module, const char* pkg, jobject to_module, 136 jboolean open) { 137 static jmethodID mIsExportedTo = NULL; 138 jstring jstr = NULL; 139 jboolean res = JNI_FALSE; 140 141 if (mIsExportedTo == NULL) { 142 const char* sign = "(Ljava/lang/String;Ljava/lang/reflect/Module;)Z"; 143 const char* name = open ? "isOpen" : "isExported"; 144 mIsExportedTo = get_method(env, jlrM(env), name, sign); 145 } 146 jstr = JNI_ENV_PTR(env)->NewStringUTF(JNI_ENV_ARG(env, pkg)); 147 res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module), 148 mIsExportedTo, jstr, to_module); 149 return res; 150} 151 152static 153jvmtiError add_module_exports(jobject baseModule, const char* pkg, jobject thisModule, 154 jboolean open) { 155 jvmtiError err = JVMTI_ERROR_NONE; 156 if (open) { 157 err = (*jvmti)->AddModuleOpens(jvmti, baseModule, pkg, thisModule); 158 } else { 159 err = (*jvmti)->AddModuleExports(jvmti, baseModule, pkg, thisModule); 160 } 161 return err; 162} 163 164static 165jint check_add_module_exports(JNIEnv *env, 166 jclass cls, 167 jobject baseModule, 168 jobject thisModule, 169 jboolean open) { 170 static char strbuf[128] = { '\0' }; 171 jvmtiError err = JVMTI_ERROR_NONE; 172 const char* pkg = open ? "jdk.internal.math" 173 : "jdk.internal.misc"; 174 const char* bad_pkg = "my.bad.pkg"; 175 const char* jvmti_fn = open ? "AddModuleOpens" 176 : "AddModuleExports"; 177 jboolean exported = JNI_FALSE; 178 179 // Export from NULL module 180 printf("Check #N1:\n"); 181 err = add_module_exports(NULL, pkg, thisModule, open); 182 if (err != JVMTI_ERROR_NULL_POINTER) { 183 printf("#N1: jvmtiError from %s: %d\n", jvmti_fn, err); 184 throw_exc(env, "Check #N1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL"); 185 return FAILED; 186 } 187 188 // Export NULL package 189 printf("Check #N2:\n"); 190 err = add_module_exports(baseModule, NULL, thisModule, open); 191 if (err != JVMTI_ERROR_NULL_POINTER) { 192 printf("#N2: jvmtiError from %s: %d\n", jvmti_fn, err); 193 throw_exc(env, "Check #N2: failed to return JVMTI_ERROR_NULL_POINTER for pkg==NULL"); 194 return FAILED; 195 } 196 197 // Export to NULL module 198 printf("Check #N3:\n"); 199 err = add_module_exports(baseModule, pkg, NULL, open); 200 if (err != JVMTI_ERROR_NULL_POINTER) { 201 printf("#N3: jvmtiError from %s: %d\n", jvmti_fn, err); 202 throw_exc(env, "Check #N3: failed to return JVMTI_ERROR_NULL_POINTER for to_module==NULL"); 203 return FAILED; 204 } 205 206 // Export a bad package 207 printf("Check #I0:\n"); 208 err = add_module_exports(baseModule, bad_pkg, thisModule, open); 209 if (err != JVMTI_ERROR_ILLEGAL_ARGUMENT) { 210 printf("#I0: jvmtiError from %s: %d\n", jvmti_fn, err); 211 throw_exc(env, "Check #I0: did not get expected JVMTI_ERROR_ILLEGAL_ARGUMENT for invalid package"); 212 return FAILED; 213 } 214 215 // Export from invalid module (cls) 216 printf("Check #I1:\n"); 217 err = add_module_exports((jobject)cls, pkg, thisModule, open); 218 if (err != JVMTI_ERROR_INVALID_MODULE) { 219 printf("#I1: jvmtiError from %s: %d\n", jvmti_fn, err); 220 throw_exc(env, "Check #I1: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid module"); 221 return FAILED; 222 } 223 224 // Export to invalid module (cls) 225 printf("Check #I2:\n"); 226 err = add_module_exports(baseModule, pkg, (jobject)cls, open); 227 if (err != JVMTI_ERROR_INVALID_MODULE) { 228 printf("#I2: jvmtiError from %s: %d\n", jvmti_fn, err); 229 throw_exc(env, "Check #I2: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid to_module"); 230 return FAILED; 231 } 232 233 // Check the pkg is not exported from baseModule to thisModule 234 printf("Check #C0:\n"); 235 exported = is_exported_to(env, baseModule, pkg, thisModule, open); 236 if (exported != JNI_FALSE) { 237 sprintf(strbuf, "Check #C0: unexpected export of %s from base to this", pkg); 238 throw_exc(env, strbuf); 239 return FAILED; 240 } 241 242 // Add export of the pkg from baseModule to thisModule 243 printf("Check #C1:\n"); 244 err = add_module_exports(baseModule, pkg, thisModule, open); 245 if (err != JVMTI_ERROR_NONE) { 246 printf("#C1: jvmtiError from %s: %d\n", jvmti_fn, err); 247 sprintf(strbuf, "Check #C1: error in add export of %s from base to this", pkg); 248 throw_exc(env, strbuf); 249 return FAILED; 250 } 251 252 // Check the pkg is exported from baseModule to thisModule 253 printf("Check #C2:\n"); 254 exported = is_exported_to(env, baseModule, pkg, thisModule, open); 255 if (exported == JNI_FALSE) { 256 sprintf(strbuf, "Check #C2: failed to export %s from base to this", pkg); 257 throw_exc(env, strbuf); 258 return FAILED; 259 } 260 261 // Check the pkg is not exported to all modules 262 printf("Check #C3:\n"); 263 exported = is_exported(env, baseModule, pkg, open); 264 if (exported != JNI_FALSE) { 265 sprintf(strbuf, "Check #C3: unexpected export of %s from base to all modules", pkg); 266 throw_exc(env, strbuf); 267 return FAILED; 268 } 269 return PASSED; 270} 271 272JNIEXPORT jint JNICALL 273Java_MyPackage_AddModuleExportsAndOpensTest_check(JNIEnv *env, 274 jclass cls, 275 jobject baseModule, 276 jobject thisModule) { 277 if (jvmti == NULL) { 278 throw_exc(env, "JVMTI client was not properly loaded!\n"); 279 return FAILED; 280 } 281 282 printf("\n*** Checks for JVMTI AddModuleExports ***\n\n"); 283 result = check_add_module_exports(env, cls, baseModule, thisModule, JNI_FALSE); 284 if (result != PASSED) { 285 return result; 286 } 287 288 printf("\n*** Checks for JVMTI AddModuleOpens ***\n\n"); 289 result = check_add_module_exports(env, cls, baseModule, thisModule, JNI_TRUE); 290 if (result != PASSED) { 291 return result; 292 } 293 return result; 294} 295 296#ifdef __cplusplus 297} 298#endif 299