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
29 extern "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
49 static const char *EXC_CNAME = "java/lang/Exception";
50 static const char* MOD_CNAME = "Ljava/lang/Module;";
51
52 static jvmtiEnv *jvmti = NULL;
53 static jint result = PASSED;
54
55 static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
56
57 JNIEXPORT
Agent_OnLoad(JavaVM * jvm,char * options,void * reserved)58 jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
59 return Agent_Initialize(jvm, options, reserved);
60 }
61
62 JNIEXPORT
Agent_OnAttach(JavaVM * jvm,char * options,void * reserved)63 jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
64 return Agent_Initialize(jvm, options, reserved);
65 }
66
67 JNIEXPORT
JNI_OnLoad(JavaVM * jvm,void * reserved)68 jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
69 return JNI_VERSION_1_8;
70 }
71
72 static
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)73 jint 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
84 static
throw_exc(JNIEnv * env,char * msg)85 void 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
99 static
jlM(JNIEnv * env)100 jclass 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
110 jmethodID
get_method(JNIEnv * env,jclass clazz,const char * name,const char * sig)111 get_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
121 static
can_use_service(JNIEnv * env,jobject module,jclass service)122 jboolean 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
135 JNIEXPORT jint JNICALL
Java_MyPackage_AddModuleUsesAndProvidesTest_checkUses(JNIEnv * env,jclass cls,jobject baseModule,jclass service)136 Java_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
207 JNIEXPORT jint JNICALL
Java_MyPackage_AddModuleUsesAndProvidesTest_checkProvides(JNIEnv * env,jclass cls,jobject baseModule,jclass service,jclass serviceImpl)208 Java_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