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