libAddModuleReadsTest.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 return JNI_OK; 81} 82 83static 84jint throw_exc(JNIEnv *env, char *msg) { 85 jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); 86 87 if (exc_class == NULL) { 88 printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); 89 return -1; 90 } 91 return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); 92} 93 94static 95jclass jlrM(JNIEnv *env) { 96 jclass cls = NULL; 97 98 cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME)); 99 if (cls == NULL) { 100 printf(" Error in JNI FindClass: %s\n", MOD_CNAME); 101 } 102 return cls; 103} 104 105jmethodID 106get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) { 107 jmethodID method = NULL; 108 109 method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig); 110 if (method == NULL) { 111 printf(" Error in JNI GetMethodID %s with signature %s", name, sig); 112 } 113 return method; 114} 115 116static 117jboolean can_module_read(JNIEnv *env, jobject module, jobject to_module) { 118 static jmethodID mCanRead = NULL; 119 jboolean res = JNI_FALSE; 120 121 if (mCanRead == NULL) { 122 const char* sign = "(Ljava/lang/reflect/Module;)Z"; 123 mCanRead = get_method(env, jlrM(env), "canRead", sign); 124 } 125 res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module), 126 mCanRead, to_module); 127 return res; 128} 129 130static 131jint check_add_module_reads(JNIEnv *env, 132 jclass cls, 133 jobject unnamedModule, 134 jobject baseModule, 135 jobject instrModule) { 136 jvmtiError err = JVMTI_ERROR_NONE; 137 jboolean can = JNI_FALSE; 138 139 // Add an invalid read edge from NULL module 140 printf("Check #N1:\n"); 141 err = (*jvmti)->AddModuleReads(jvmti, NULL, baseModule); 142 if (err != JVMTI_ERROR_NULL_POINTER) { 143 printf("#N1: jvmtiError from AddModuleReads: %d\n", err); 144 throw_exc(env, "Check #N1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL"); 145 return FAILED; 146 } 147 148 // Add an invalid read edge to NULL module 149 printf("Check #N2:\n"); 150 err = (*jvmti)->AddModuleReads(jvmti, baseModule, NULL); 151 if (err != JVMTI_ERROR_NULL_POINTER) { 152 printf("#N2: jvmtiError from AddModuleReads: %d\n", err); 153 throw_exc(env, "Check #N2: failed to return JVMTI_ERROR_NULL_POINTER for to_module==NULL"); 154 return FAILED; 155 } 156 157 // Add an invalid read edge from invalid module (cls) 158 printf("Check #I1:\n"); 159 err = (*jvmti)->AddModuleReads(jvmti, cls, baseModule); 160 if (err != JVMTI_ERROR_INVALID_MODULE) { 161 printf("#I1: jvmtiError from AddModuleReads: %d\n", err); 162 throw_exc(env, "Check #I1: failed to return JVMTI_ERROR_INVALID_MODULE for module==cls"); 163 return FAILED; 164 } 165 166 // Add an invalid read edge to invalid module (cls) 167 printf("Check #I2:\n"); 168 err = (*jvmti)->AddModuleReads(jvmti, baseModule, cls); 169 if (err != JVMTI_ERROR_INVALID_MODULE) { 170 printf("#I2: jvmtiError from AddModuleReads: %d\n", err); 171 throw_exc(env, "Check #I2: failed to return JVMTI_ERROR_INVALID_MODULE for to_module==cls"); 172 return FAILED; 173 } 174 175 // Check the edge baseModule->instrModule is absent 176 printf("Check #C0:\n"); 177 can = can_module_read(env, baseModule, instrModule); 178 if (can != JNI_FALSE) { 179 throw_exc(env, "Check #C0: read edge from base to instr is unexpected"); 180 return FAILED; 181 } 182 183 // Add read edge baseModule->instrModule 184 printf("Check #C1:\n"); 185 err = (*jvmti)->AddModuleReads(jvmti, baseModule, instrModule); 186 if (err != JVMTI_ERROR_NONE) { 187 printf("#C1: jvmtiError from AddModuleReads: %d\n", err); 188 throw_exc(env, "Check #C1: error in add reads from base to instr"); 189 return FAILED; 190 } 191 192 // Check the read edge baseModule->instrModule is present now 193 printf("Check #C2:\n"); 194 can = can_module_read(env, baseModule, instrModule); 195 if (can == JNI_FALSE) { 196 throw_exc(env, "Check #C2: failed to add reads from base to instr"); 197 return FAILED; 198 } 199 200 // Check the read edge baseModule->unnamedModule is absent 201 printf("Check #C3:\n"); 202 can = can_module_read(env, baseModule, unnamedModule); 203 if (can != JNI_FALSE) { 204 throw_exc(env, "Check #C3: got unexpected read edge from base to unnamed"); 205 return FAILED; 206 } 207 208 // Add read edge baseModule->unnamedModule 209 printf("Check #C4:\n"); 210 err = (*jvmti)->AddModuleReads(jvmti, baseModule, unnamedModule); 211 if (err != JVMTI_ERROR_NONE) { 212 printf("#C4: jvmtiError from AddModuleReads: %d\n", err); 213 throw_exc(env, "Check #C4: failed to ignore adding read edge from base to unnamed"); 214 return FAILED; 215 } 216 217 // Check the read edge baseModule->unnamedModule is present now 218 printf("Check #C5:\n"); 219 can = can_module_read(env, baseModule, unnamedModule); 220 if (can == JNI_FALSE) { 221 throw_exc(env, "Check #C5: did not get expected read edge from base to unnamed"); 222 return FAILED; 223 } 224 225 // Check the read edge unnamedModule->instrModule is absent 226 printf("Check #C6:\n"); 227 can = can_module_read(env, unnamedModule, instrModule); 228 if (can == JNI_FALSE) { 229 throw_exc(env, "Check #C6: did not get expected read edge from unnamed to instr"); 230 return FAILED; 231 } 232 233 // Add read edge unnamedModule->instrModule 234 printf("Check #C7:\n"); 235 err = (*jvmti)->AddModuleReads(jvmti, unnamedModule, instrModule); 236 if (err != JVMTI_ERROR_NONE) { 237 printf("#C7: jvmtiError from AddModuleReads: %d\n", err); 238 throw_exc(env, "Check #C7: failed to ignore adding read edge from unnamed to instr"); 239 return FAILED; 240 } 241 return PASSED; 242} 243 244JNIEXPORT jint JNICALL 245Java_MyPackage_AddModuleReadsTest_check(JNIEnv *env, 246 jclass cls, 247 jobject unnamedModule, 248 jobject baseModule, 249 jobject instrModule) { 250 if (jvmti == NULL) { 251 throw_exc(env, "JVMTI client was not properly loaded!\n"); 252 return FAILED; 253 } 254 255 printf("\n*** Checks for JVMTI AddModuleReads ***\n\n"); 256 result = check_add_module_reads(env, cls, unnamedModule, baseModule, instrModule); 257 if (result != PASSED) { 258 return result; 259 } 260 return result; 261} 262 263#ifdef __cplusplus 264} 265#endif 266