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 81 return JNI_OK; 82} 83 84static 85void throw_exc(JNIEnv *env, char *msg) { 86 jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); 87 jint rt = JNI_OK; 88 89 if (exc_class == NULL) { 90 printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); 91 return; 92 } 93 rt = JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); 94 if (rt == JNI_ERR) { 95 printf("throw_exc: Error in JNI ThrowNew(env, %s)\n", msg); 96 } 97} 98 99static 100jclass jlM(JNIEnv *env) { 101 jclass cls = NULL; 102 103 cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME)); 104 if (cls == NULL) { 105 printf(" Error in JNI FindClass: %s\n", MOD_CNAME); 106 } 107 return cls; 108} 109 110jmethodID 111get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) { 112 jmethodID method = NULL; 113 114 method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig); 115 if (method == NULL) { 116 printf(" Error in JNI GetMethodID %s with signature %s", name, sig); 117 } 118 return method; 119} 120 121static 122jboolean can_use_service(JNIEnv *env, jobject module, jclass service) { 123 static jmethodID mCanUse = NULL; 124 jboolean res = JNI_FALSE; 125 126 if (mCanUse == NULL) { 127 const char* sign = "(Ljava/lang/Class;)Z"; 128 mCanUse = get_method(env, jlM(env), "canUse", sign); 129 } 130 res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module), 131 mCanUse, service); 132 return res; 133} 134 135JNIEXPORT jint JNICALL 136Java_MyPackage_AddModuleUsesAndProvidesTest_checkUses(JNIEnv *env, 137 jclass cls, 138 jobject baseModule, 139 jclass service) { 140 jvmtiError err = JVMTI_ERROR_NONE; 141 jboolean used = JNI_FALSE; 142 143 // Add a service to use to NULL module 144 printf("Check #UN1:\n"); 145 err = (*jvmti)->AddModuleUses(jvmti, NULL, service); 146 if (err != JVMTI_ERROR_NULL_POINTER) { 147 printf("#UN1: jvmtiError from AddModuleUses: %d\n", err); 148 throw_exc(env, "Check #UN1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL"); 149 return FAILED; 150 } 151 152 // Add NULL service to use to baseModule 153 printf("Check #UN2:\n"); 154 err = (*jvmti)->AddModuleUses(jvmti, baseModule, NULL); 155 if (err != JVMTI_ERROR_NULL_POINTER) { 156 printf("#UN2: jvmtiError from AddModuleUses: %d\n", err); 157 throw_exc(env, "Check #UN2: failed to return JVMTI_ERROR_NULL_POINTER for service==NULL"); 158 return FAILED; 159 } 160 161 // Add service to use to invalid module (cls) 162 printf("Check #UI1:\n"); 163 err = (*jvmti)->AddModuleUses(jvmti, (jobject)cls, service); 164 if (err != JVMTI_ERROR_INVALID_MODULE) { 165 printf("#UI1: jvmtiError from AddModuleUses: %d\n", err); 166 throw_exc(env, "Check #UI1: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid module"); 167 return FAILED; 168 } 169 170 // Add invalid service (thisModule) to use to baseModule 171 printf("Check #UI2:\n"); 172 err = (*jvmti)->AddModuleUses(jvmti, baseModule, baseModule); 173 if (err != JVMTI_ERROR_INVALID_CLASS) { 174 printf("#UI2: jvmtiError from AddModuleUses: %d\n", err); 175 throw_exc(env, "Check #UI2: did not get expected JVMTI_ERROR_INVALID_CLASS for invalid service"); 176 return FAILED; 177 } 178 179 // Check if the service can not be used 180 printf("Check #UC1:\n"); 181 used = can_use_service(env, baseModule, service); 182 if (used != JNI_FALSE) { 183 throw_exc(env, "Check #UC1: unexpected use of service"); 184 return FAILED; 185 } 186 187 // Add uses of a correct service 188 printf("Check #UC2:\n"); 189 err = (*jvmti)->AddModuleUses(jvmti, baseModule, service); 190 if (err != JVMTI_ERROR_NONE) { 191 printf("#UC2: jvmtiError from AddModuleUses: %d\n", err); 192 throw_exc(env, "Check #UC2: got unexpected JVMTI error"); 193 return FAILED; 194 } 195 196 // Check if the service can not be used 197 printf("Check #UC3:\n"); 198 used = can_use_service(env, baseModule, service); 199 if (used == JNI_FALSE) { 200 throw_exc(env, "Check #UC3: service can not be used unexpectedly"); 201 return FAILED; 202 } 203 fflush(0); 204 return PASSED; 205} 206 207JNIEXPORT jint JNICALL 208Java_MyPackage_AddModuleUsesAndProvidesTest_checkProvides(JNIEnv *env, 209 jclass cls, 210 jobject baseModule, 211 jclass service, 212 jclass serviceImpl) { 213 jvmtiError err = JVMTI_ERROR_NONE; 214 jboolean provided = JNI_FALSE; 215 216 // Add provides to NULL module 217 printf("Check #PN1:\n"); 218 err = (*jvmti)->AddModuleProvides(jvmti, NULL, service, serviceImpl); 219 if (err != JVMTI_ERROR_NULL_POINTER) { 220 printf("#PN1: jvmtiError from AddModuleProvides: %d\n", err); 221 throw_exc(env, "Check #PN1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL"); 222 return FAILED; 223 } 224 225 // Add provides with NULL service 226 printf("Check #PN2:\n"); 227 err = (*jvmti)->AddModuleProvides(jvmti, baseModule, NULL, serviceImpl); 228 if (err != JVMTI_ERROR_NULL_POINTER) { 229 printf("#PN2: jvmtiError from AddModuleProvides: %d\n", err); 230 throw_exc(env, "Check #PN2: failed to return JVMTI_ERROR_NULL_POINTER for service==NULL"); 231 return FAILED; 232 } 233 234 // Add provides with NULL serviceImpl 235 printf("Check #PN3:\n"); 236 err = (*jvmti)->AddModuleProvides(jvmti, baseModule, service, NULL); 237 if (err != JVMTI_ERROR_NULL_POINTER) { 238 printf("#PN3: jvmtiError from AddModuleProvides: %d\n", err); 239 throw_exc(env, "Check #PN3: failed to return JVMTI_ERROR_NULL_POINTER for serviceImpl==NULL"); 240 return FAILED; 241 } 242 243 // Add provides to invalid module (cls) 244 printf("Check #PI1:\n"); 245 err = (*jvmti)->AddModuleProvides(jvmti, (jobject)cls, service, serviceImpl); 246 if (err != JVMTI_ERROR_INVALID_MODULE) { 247 printf("#PI1: jvmtiError from AddModuleProvides: %d\n", err); 248 throw_exc(env, "Check #PI1: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid module"); 249 return FAILED; 250 } 251 252 // Add provides with invalid service (baseModule) 253 printf("Check #PI2:\n"); 254 err = (*jvmti)->AddModuleProvides(jvmti, baseModule, baseModule, serviceImpl); 255 if (err != JVMTI_ERROR_INVALID_CLASS) { 256 printf("#PI2: jvmtiError from AddModuleProvides: %d\n", err); 257 throw_exc(env, "Check #PI2: did not get expected JVMTI_ERROR_INVALID_CLASS for invalid service"); 258 return FAILED; 259 } 260 261 // Add provides with invalid serviceImpl (baseModule) 262 printf("Check #PI3:\n"); 263 err = (*jvmti)->AddModuleProvides(jvmti, baseModule, service, baseModule); 264 if (err != JVMTI_ERROR_INVALID_CLASS) { 265 printf("#PI3: jvmtiError from AddModuleProvides: %d\n", err); 266 throw_exc(env, "Check #PI3: did not get expected JVMTI_ERROR_INVALID_CLASS for invalid serviceImpl"); 267 return FAILED; 268 } 269 270 // Add provides to baseModule with correct service and serviceImpl 271 printf("Check #PC2:\n"); 272 err = (*jvmti)->AddModuleProvides(jvmti, baseModule, service, serviceImpl); 273 if (err != JVMTI_ERROR_NONE) { 274 printf("#PC2: jvmtiError from AddModuleExports: %d\n", err); 275 throw_exc(env, "Check #PC2: error in add provides to baseModule with correct service and serviceImpl"); 276 return FAILED; 277 } 278 fflush(0); 279 return PASSED; 280} 281 282#ifdef __cplusplus 283} 284#endif 285