30 #include "agent_common.h" |
30 #include "agent_common.h" |
31 |
31 |
32 #include "JVMTITools.h" |
32 #include "JVMTITools.h" |
33 #include "native_thread.h" |
33 #include "native_thread.h" |
34 |
34 |
35 #ifdef __cplusplus |
|
36 extern "C" { |
35 extern "C" { |
37 #endif |
36 |
38 |
|
39 #ifndef JNI_ENV_ARG |
|
40 #ifdef __cplusplus |
|
41 #define JNI_ENV_ARG(x, y) y |
|
42 #define JNI_ENV_PTR(x) x |
|
43 #else |
|
44 #define JNI_ENV_ARG(x, y) x, y |
|
45 #define JNI_ENV_PTR(x) (*x) |
|
46 #endif |
|
47 #endif |
|
48 |
|
49 #ifndef JNI_ENV_ARG1 |
|
50 #ifdef __cplusplus |
|
51 #define JNI_ENV_ARG1(x) |
|
52 #else |
|
53 #define JNI_ENV_ARG1(x) x |
|
54 #endif |
|
55 #endif |
|
56 |
37 |
57 #define PASSED 0 |
38 #define PASSED 0 |
58 #define STATUS_FAILED 2 |
39 #define STATUS_FAILED 2 |
59 |
40 |
60 #define TRIES 30 |
41 #define TRIES 30 |
138 if ((err = jvmti->GetJNIFunctionTable(&orig_jni_functions)) != |
119 if ((err = jvmti->GetJNIFunctionTable(&orig_jni_functions)) != |
139 JVMTI_ERROR_NONE) { |
120 JVMTI_ERROR_NONE) { |
140 result = STATUS_FAILED; |
121 result = STATUS_FAILED; |
141 printf("(%s,%d): TEST FAILED: failed to get original JNI function table: %s\n", |
122 printf("(%s,%d): TEST FAILED: failed to get original JNI function table: %s\n", |
142 __FILE__, __LINE__, TranslateError(err)); |
123 __FILE__, __LINE__, TranslateError(err)); |
143 JNI_ENV_PTR(env)->FatalError(JNI_ENV_ARG(env, |
124 env->FatalError("failed to get original JNI function table"); |
144 "failed to get original JNI function table")); |
|
145 } |
125 } |
146 if ((err = jvmti->GetJNIFunctionTable(&redir_jni_functions)) != |
126 if ((err = jvmti->GetJNIFunctionTable(&redir_jni_functions)) != |
147 JVMTI_ERROR_NONE) { |
127 JVMTI_ERROR_NONE) { |
148 result = STATUS_FAILED; |
128 result = STATUS_FAILED; |
149 printf("(%s,%d): TEST FAILED: failed to get redirected JNI function table: %s\n", |
129 printf("(%s,%d): TEST FAILED: failed to get redirected JNI function table: %s\n", |
150 __FILE__, __LINE__, TranslateError(err)); |
130 __FILE__, __LINE__, TranslateError(err)); |
151 JNI_ENV_PTR(env)->FatalError(JNI_ENV_ARG(env, |
131 env->FatalError("failed to get redirected JNI function table"); |
152 "failed to get redirected JNI function table")); |
|
153 } |
132 } |
154 if (verbose) |
133 if (verbose) |
155 printf("doRedirect: the JNI function table obtained successfully\n"); |
134 printf("doRedirect: the JNI function table obtained successfully\n"); |
156 |
135 |
157 if (verbose) |
136 if (verbose) |
161 if ((err = jvmti->SetJNIFunctionTable(redir_jni_functions)) != |
140 if ((err = jvmti->SetJNIFunctionTable(redir_jni_functions)) != |
162 JVMTI_ERROR_NONE) { |
141 JVMTI_ERROR_NONE) { |
163 result = STATUS_FAILED; |
142 result = STATUS_FAILED; |
164 printf("(%s,%d): TEST FAILED: failed to set new JNI function table: %s\n", |
143 printf("(%s,%d): TEST FAILED: failed to set new JNI function table: %s\n", |
165 __FILE__, __LINE__, TranslateError(err)); |
144 __FILE__, __LINE__, TranslateError(err)); |
166 JNI_ENV_PTR(env)->FatalError(JNI_ENV_ARG(env, |
145 env->FatalError("failed to set new JNI function table"); |
167 "failed to set new JNI function table")); |
|
168 } |
146 } |
169 |
147 |
170 if (verbose) |
148 if (verbose) |
171 printf("\ndoRedirect: the functions are overwritten successfully\n"); |
149 printf("\ndoRedirect: the functions are overwritten successfully\n"); |
172 } |
150 } |
179 if ((err = jvmti->SetJNIFunctionTable(orig_jni_functions)) != |
157 if ((err = jvmti->SetJNIFunctionTable(orig_jni_functions)) != |
180 JVMTI_ERROR_NONE) { |
158 JVMTI_ERROR_NONE) { |
181 result = STATUS_FAILED; |
159 result = STATUS_FAILED; |
182 printf("(%s,%d): TEST FAILED: failed to restore original JNI function table: %s\n", |
160 printf("(%s,%d): TEST FAILED: failed to restore original JNI function table: %s\n", |
183 __FILE__, __LINE__, TranslateError(err)); |
161 __FILE__, __LINE__, TranslateError(err)); |
184 JNI_ENV_PTR(env)->FatalError(JNI_ENV_ARG(env, |
162 env->FatalError("failed to restore original JNI function table"); |
185 "failed to restore original JNI function table")); |
|
186 } |
163 } |
187 if (verbose) |
164 if (verbose) |
188 printf("doRestore: the original JNI function table is restored successfully\n"); |
165 printf("doRestore: the original JNI function table is restored successfully\n"); |
189 } |
166 } |
190 |
167 |
191 void doExec(JNIEnv *env, int thrNum) { |
168 void doExec(JNIEnv *env, int thrNum) { |
192 jint res; |
169 jint res; |
193 |
170 |
194 if ((res = JNI_ENV_PTR(env)-> |
171 if ((res = env->MonitorEnter(clsObj)) != 0) { |
195 MonitorEnter(JNI_ENV_ARG(env, clsObj))) != 0) { |
|
196 result = STATUS_FAILED; |
172 result = STATUS_FAILED; |
197 printf("(%s,%d): TEST FAILURE: MonitorEnter() returns %d for thread #%d\n", |
173 printf("(%s,%d): TEST FAILURE: MonitorEnter() returns %d for thread #%d\n", |
198 __FILE__, __LINE__, res, thrNum); |
174 __FILE__, __LINE__, res, thrNum); |
199 } |
175 } |
200 if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG1(env))) { |
176 if (env->ExceptionOccurred()) { |
201 result = STATUS_FAILED; |
177 result = STATUS_FAILED; |
202 printf("(%s,%d): TEST FAILURE: exception occured for thread #%d\n", |
178 printf("(%s,%d): TEST FAILURE: exception occured for thread #%d\n", |
203 __FILE__, __LINE__, thrNum); |
179 __FILE__, __LINE__, thrNum); |
204 JNI_ENV_PTR(env)->ExceptionDescribe(JNI_ENV_ARG1(env)); |
180 env->ExceptionDescribe(); |
205 JNI_ENV_PTR(env)->ExceptionClear(JNI_ENV_ARG1(env)); |
181 env->ExceptionClear(); |
206 } |
182 } |
207 if (verbose) |
183 if (verbose) |
208 printf("\ndoExec: thread #%d entered the monitor\n", |
184 printf("\ndoExec: thread #%d entered the monitor\n", |
209 thrNum); |
185 thrNum); |
210 if ((res = JNI_ENV_PTR(env)-> |
186 if ((res = env->MonitorExit(clsObj)) != 0) { |
211 MonitorExit(JNI_ENV_ARG(env, clsObj))) != 0) { |
|
212 result = STATUS_FAILED; |
187 result = STATUS_FAILED; |
213 printf("(%s,%d): TEST FAILURE: MonitorExit() returns %d for thread #%d\n", |
188 printf("(%s,%d): TEST FAILURE: MonitorExit() returns %d for thread #%d\n", |
214 __FILE__, __LINE__, res, thrNum); |
189 __FILE__, __LINE__, res, thrNum); |
215 } |
190 } |
216 if (verbose) |
191 if (verbose) |
244 int indx = *((int *) context); |
219 int indx = *((int *) context); |
245 |
220 |
246 if (verbose) |
221 if (verbose) |
247 printf("\nwaitingThread: thread #%d started\n\tattaching the thread to the VM ...\n", |
222 printf("\nwaitingThread: thread #%d started\n\tattaching the thread to the VM ...\n", |
248 indx); |
223 indx); |
249 if ((res = |
224 if ((res = vm->AttachCurrentThread((void **) &env, (void *) 0)) != 0) { |
250 JNI_ENV_PTR(vm)->AttachCurrentThread( |
|
251 JNI_ENV_ARG(vm, (void **) &env), (void *) 0)) != 0) { |
|
252 printf("(%s,%d): TEST FAILURE: waitingThread: AttachCurrentThread() returns: %d\n", |
225 printf("(%s,%d): TEST FAILURE: waitingThread: AttachCurrentThread() returns: %d\n", |
253 __FILE__, __LINE__, res); |
226 __FILE__, __LINE__, res); |
254 return STATUS_FAILED; |
227 return STATUS_FAILED; |
255 } |
228 } |
256 |
229 |
257 thrStarted[indx-1] = 1; |
230 thrStarted[indx-1] = 1; |
258 |
231 |
259 doExec(env, indx); |
232 doExec(env, indx); |
260 |
233 |
261 if ((res = |
234 if ((res = vm->DetachCurrentThread()) != 0) { |
262 JNI_ENV_PTR(vm)->DetachCurrentThread( |
|
263 JNI_ENV_ARG1(vm))) != 0) { |
|
264 printf("(%s,%d): TEST FAILURE: waitingThread: DetachCurrentThread() returns: %d\n", |
235 printf("(%s,%d): TEST FAILURE: waitingThread: DetachCurrentThread() returns: %d\n", |
265 __FILE__, __LINE__, res); |
236 __FILE__, __LINE__, res); |
266 return STATUS_FAILED; |
237 return STATUS_FAILED; |
267 } |
238 } |
268 if (verbose) |
239 if (verbose) |
274 |
245 |
275 static jobject getObjectFromField(JNIEnv *env, jobject obj) { |
246 static jobject getObjectFromField(JNIEnv *env, jobject obj) { |
276 jfieldID fid; |
247 jfieldID fid; |
277 jclass _objCls; |
248 jclass _objCls; |
278 |
249 |
279 _objCls = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG(env, obj)); |
250 _objCls = env->GetObjectClass(obj); |
280 |
251 |
281 if (verbose) |
252 if (verbose) |
282 printf("\ngetObjectFromField: obtaining field ID for name=\"%s\" signature=\"%s\"...\n", |
253 printf("\ngetObjectFromField: obtaining field ID for name=\"%s\" signature=\"%s\"...\n", |
283 javaField, classSig); |
254 javaField, classSig); |
284 if ((fid = JNI_ENV_PTR(env)->GetFieldID( |
255 if ((fid = env->GetFieldID(_objCls, javaField, classSig)) == 0) { |
285 JNI_ENV_ARG(env, _objCls), javaField, classSig)) == 0) { |
|
286 result = STATUS_FAILED; |
256 result = STATUS_FAILED; |
287 printf("(%s,%d): TEST FAILURE: failed to get ID for the field \"%s\"\n", |
257 printf("(%s,%d): TEST FAILURE: failed to get ID for the field \"%s\"\n", |
288 __FILE__, __LINE__, javaField); |
258 __FILE__, __LINE__, javaField); |
289 JNI_ENV_PTR(env)->FatalError(JNI_ENV_ARG(env, |
259 env->FatalError("failed to get ID for the java field"); |
290 "failed to get ID for the java field")); |
260 } |
291 } |
261 |
292 |
262 return env->GetObjectField(obj, fid); |
293 return JNI_ENV_PTR(env)->GetObjectField( |
|
294 JNI_ENV_ARG(env, obj), fid); |
|
295 } |
263 } |
296 |
264 |
297 void startThreads() { |
265 void startThreads() { |
298 int i; |
266 int i; |
299 int tries = 0; |
267 int tries = 0; |
356 printf("(%s,%d): TEST FAILURE: JVMTI client was not properly loaded\n", |
324 printf("(%s,%d): TEST FAILURE: JVMTI client was not properly loaded\n", |
357 __FILE__, __LINE__); |
325 __FILE__, __LINE__); |
358 return STATUS_FAILED; |
326 return STATUS_FAILED; |
359 } |
327 } |
360 |
328 |
361 if ((clsObj = JNI_ENV_PTR(env)->NewGlobalRef( |
329 if ((clsObj = env->NewGlobalRef(getObjectFromField(env, obj))) == NULL) { |
362 JNI_ENV_ARG(env, getObjectFromField(env, obj)))) == NULL) { |
|
363 printf("(%s,%d): TEST FAILURE: cannot create a new global reference of class \"%s\"\n", |
330 printf("(%s,%d): TEST FAILURE: cannot create a new global reference of class \"%s\"\n", |
364 __FILE__, __LINE__, classSig); |
331 __FILE__, __LINE__, classSig); |
365 JNI_ENV_PTR(env)->FatalError(JNI_ENV_ARG(env, |
332 env->FatalError("failed to create a new global reference"); |
366 "failed to create a new global reference")); |
|
367 } |
333 } |
368 |
334 |
369 doRedirect(env); |
335 doRedirect(env); |
370 |
336 |
371 /* 1: check the assertion inside current thread and new threads */ |
337 /* 1: check the assertion inside current thread and new threads */ |
383 Note: the JNI spec says that the main thread can be detached from the VM |
349 Note: the JNI spec says that the main thread can be detached from the VM |
384 only since JDK 1.2 */ |
350 only since JDK 1.2 */ |
385 if (verbose) |
351 if (verbose) |
386 printf("\nb) Checking the assertion inside main thread detached and attached again ...\n\ndetaching the main thread ...\n"); |
352 printf("\nb) Checking the assertion inside main thread detached and attached again ...\n\ndetaching the main thread ...\n"); |
387 |
353 |
388 if ((res = |
354 if ((res = vm->DetachCurrentThread()) != 0) |
389 JNI_ENV_PTR(vm)->DetachCurrentThread( |
|
390 JNI_ENV_ARG1(vm))) != 0) |
|
391 printf("(%s,%d): Warning: DetachCurrentThread() returns: %d\n\ |
355 printf("(%s,%d): Warning: DetachCurrentThread() returns: %d\n\ |
392 \tcheck with the detached main thread skipped\n", |
356 \tcheck with the detached main thread skipped\n", |
393 __FILE__, __LINE__, res); |
357 __FILE__, __LINE__, res); |
394 else { |
358 else { |
395 if (verbose) |
359 if (verbose) |
396 printf("\nattaching the main thread again ...\n"); |
360 printf("\nattaching the main thread again ...\n"); |
397 if ((res = |
361 if ((res = vm->AttachCurrentThread((void **) &nextEnv, (void *) 0)) != 0) { |
398 JNI_ENV_PTR(vm)->AttachCurrentThread( |
|
399 JNI_ENV_ARG(vm, (void **) &nextEnv), (void *) 0)) != 0) { |
|
400 printf("(%s,%d): TEST FAILURE: waitingThread: AttachCurrentThread() returns: %d\n", |
362 printf("(%s,%d): TEST FAILURE: waitingThread: AttachCurrentThread() returns: %d\n", |
401 __FILE__, __LINE__, res); |
363 __FILE__, __LINE__, res); |
402 return STATUS_FAILED; |
364 return STATUS_FAILED; |
403 } |
365 } |
404 |
366 |