1 /*
2  * Copyright (c) 2003, 2018, 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 <string.h>
25 #include "jvmti.h"
26 #include "agent_common.h"
27 #include "jni_tools.h"
28 #include "jvmti_tools.h"
29 
30 extern "C" {
31 
32 /* ============================================================================= */
33 
34 static jlong timeout = 0;
35 
36 #define INFO_NONE       0x00
37 #define INFO_ALL        0xFF
38 #define INFO_OBJREF     0x01
39 #define INFO_STACKREF   0x02
40 #define INFO_HEAPROOT   0x04
41 #define INFO_HEAPOBJ    0x08
42 
43 static unsigned int info = INFO_NONE;
44 
45 #define DEBUGEE_CLASS_NAME      "nsk/jvmti/IterateOverObjectsReachableFromObject/iterobjreachobj001"
46 #define ROOT_OBJECT_CLASS_NAME  "nsk/jvmti/IterateOverObjectsReachableFromObject/iterobjreachobj001RootTestedClass"
47 #define ROOT_OBJECT_CLASS_SIG   "L" ROOT_OBJECT_CLASS_NAME ";"
48 #define CHAIN_OBJECT_CLASS_NAME "nsk/jvmti/IterateOverObjectsReachableFromObject/iterobjreachobj001TestedClass"
49 #define CHAIN_OBJECT_CLASS_SIG  "L" CHAIN_OBJECT_CLASS_NAME ";"
50 
51 #define OBJECT_FIELD_NAME               "object"
52 #define REACHABLE_CHAIN_FIELD_NAME      "reachableChain"
53 #define UNREACHABLE_CHAIN_FIELD_NAME    "unreachableChain"
54 #define TAIL_FIELD_NAME                 "tail"
55 
56 #define DEFAULT_CHAIN_LENGTH 4
57 
58 typedef struct ObjectDescStruct {
59     jlong tag;
60     jint found;
61 } ObjectDesc;
62 
63 static int chainLength = 0;
64 static int objectsCount = 0;
65 
66 static ObjectDesc* objectDescList = NULL;
67 
68 static int fakeUserData = 0;
69 static int userDataError = 0;
70 
71 /* ============================================================================= */
72 
73 /** Obtain chain of tested objects and tag them recursively. */
getChainObjects(jvmtiEnv * jvmti,JNIEnv * jni,jobject firstObject,jfieldID firstField,const char firstFieldName[],jfieldID nextField,const char nextFieldName[],int count,ObjectDesc objectDescList[],jlong tag,int reachable)74 static int getChainObjects(jvmtiEnv* jvmti, JNIEnv* jni, jobject firstObject,
75                                     jfieldID firstField, const char firstFieldName[],
76                                     jfieldID nextField, const char nextFieldName[],
77                                     int count, ObjectDesc objectDescList[],
78                                     jlong tag, int reachable) {
79     jobject obj = NULL;
80     jlong objTag = (reachable ? tag : -tag);
81 
82     if (count <= 0)
83         return NSK_TRUE;
84 
85     count--;
86     tag++;
87 
88     if (!NSK_JNI_VERIFY(jni, (obj = jni->GetObjectField(firstObject, firstField)) != NULL)) {
89         nsk_jvmti_setFailStatus();
90         return NSK_FALSE;
91     }
92 
93     objectDescList[count].tag = objTag;
94     if (!NSK_JVMTI_VERIFY(jvmti->SetTag(obj, objTag))) {
95         nsk_jvmti_setFailStatus();
96     }
97     NSK_DISPLAY2("        tag=%-5ld object=0x%p\n", (long)objTag, (void*)obj);
98 
99     if (!getChainObjects(jvmti, jni, obj, nextField, nextFieldName,
100                                 nextField, nextFieldName,
101                                 count, objectDescList, tag, reachable)) {
102         return NSK_FALSE;
103     }
104 
105     NSK_TRACE(jni->DeleteLocalRef(obj));
106     return NSK_TRUE;
107 }
108 
109 /** Obtain all tested objects from debugee class and tag them recursively. */
getTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int chainLength,int * objectsCount,ObjectDesc ** objectDescList,jobject * rootObject)110 static int getTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
111                                     int *objectsCount, ObjectDesc* *objectDescList,
112                                     jobject* rootObject) {
113     jclass debugeeClass = NULL;
114     jclass rootObjectClass = NULL;
115     jclass chainObjectClass = NULL;
116 
117     jfieldID objectField = NULL;
118     jfieldID reachableChainField = NULL;
119     jfieldID unreachableChainField = NULL;
120     jfieldID tailField = NULL;
121 
122     jlong rootObjectTag = 1;
123     jlong chainObjectTag = 100;
124 
125     *objectsCount = 1 + 2 * chainLength;
126 
127     NSK_DISPLAY1("Allocate memory for objects list: %d objects\n", *objectsCount);
128     if (!NSK_JVMTI_VERIFY(jvmti->Allocate((*objectsCount * sizeof(ObjectDesc)),
129                                           (unsigned char**)objectDescList))) {
130         nsk_jvmti_setFailStatus();
131         return NSK_FALSE;
132     }
133     NSK_DISPLAY1("  ... allocated array: 0x%p\n", (void*)objectDescList);
134 
135     {
136         int k;
137         for (k = 0; k < *objectsCount; k++) {
138             (*objectDescList)[k].tag = 0;
139             (*objectDescList)[k].found = 0;
140         }
141     }
142 
143     NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);
144     if (!NSK_JNI_VERIFY(jni, (debugeeClass = jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {
145         nsk_jvmti_setFailStatus();
146         return NSK_FALSE;
147     }
148     NSK_DISPLAY1("  ... found class: 0x%p\n", (void*)debugeeClass);
149 
150     NSK_DISPLAY1("Find root object class: %s\n", ROOT_OBJECT_CLASS_NAME);
151     if (!NSK_JNI_VERIFY(jni, (rootObjectClass = jni->FindClass(ROOT_OBJECT_CLASS_NAME)) != NULL)) {
152         nsk_jvmti_setFailStatus();
153         return NSK_FALSE;
154     }
155     NSK_DISPLAY1("  ... found class: 0x%p\n", (void*)rootObjectClass);
156 
157     NSK_DISPLAY1("Find chain object class: %s\n", CHAIN_OBJECT_CLASS_NAME);
158     if (!NSK_JNI_VERIFY(jni, (chainObjectClass =
159             jni->FindClass(CHAIN_OBJECT_CLASS_NAME)) != NULL)) {
160         nsk_jvmti_setFailStatus();
161         return NSK_FALSE;
162     }
163     NSK_DISPLAY1("  ... found class: 0x%p\n", (void*)chainObjectClass);
164 
165     NSK_DISPLAY1("Find static field in debugee class: %s\n", OBJECT_FIELD_NAME);
166     if (!NSK_JNI_VERIFY(jni, (objectField = jni->GetStaticFieldID(
167             debugeeClass, OBJECT_FIELD_NAME, ROOT_OBJECT_CLASS_SIG)) != NULL)) {
168         nsk_jvmti_setFailStatus();
169         return NSK_FALSE;
170     }
171     NSK_DISPLAY1("  ... got fieldID: 0x%p\n", (void*)objectField);
172 
173     NSK_DISPLAY1("Find instance field in root object class: %s\n", REACHABLE_CHAIN_FIELD_NAME);
174     if (!NSK_JNI_VERIFY(jni, (reachableChainField = jni->GetFieldID(
175             rootObjectClass, REACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
176         nsk_jvmti_setFailStatus();
177         return NSK_FALSE;
178     }
179     NSK_DISPLAY1("  ... got fieldID: 0x%p\n", (void*)reachableChainField);
180 
181     NSK_DISPLAY1("Find instance field in root object class: %s\n", UNREACHABLE_CHAIN_FIELD_NAME);
182     if (!NSK_JNI_VERIFY(jni, (unreachableChainField = jni->GetFieldID(
183             rootObjectClass, UNREACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
184         nsk_jvmti_setFailStatus();
185         return NSK_FALSE;
186     }
187     NSK_DISPLAY1("  ... got fieldID: 0x%p\n", (void*)unreachableChainField);
188 
189     NSK_DISPLAY1("Find instance field in chain object class: %s\n", TAIL_FIELD_NAME);
190     if (!NSK_JNI_VERIFY(jni, (tailField =
191             jni->GetFieldID(chainObjectClass, TAIL_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
192         nsk_jvmti_setFailStatus();
193         return NSK_FALSE;
194     }
195     NSK_DISPLAY1("  ... got fieldID: 0x%p\n", (void*)tailField);
196 
197     NSK_DISPLAY1("Get root object from static field: %s\n", OBJECT_FIELD_NAME);
198     if (!NSK_JNI_VERIFY(jni, (*rootObject =
199             jni->GetStaticObjectField(debugeeClass, objectField)) != NULL)) {
200         nsk_jvmti_setFailStatus();
201         return NSK_FALSE;
202     }
203     NSK_DISPLAY1("  ... got object: 0x%p\n", (void*)*rootObject);
204 
205     if (!NSK_JNI_VERIFY(jni, (*rootObject = jni->NewGlobalRef(*rootObject)) != NULL)) {
206         nsk_jvmti_setFailStatus();
207         return NSK_FALSE;
208     }
209     NSK_DISPLAY1("  ... global ref: 0x%p\n", (void*)*rootObject);
210 
211     NSK_DISPLAY0("Obtain and tag chain objects:\n");
212 
213     NSK_DISPLAY0("    root tested object:\n");
214     if (!NSK_JVMTI_VERIFY(jvmti->SetTag(*rootObject, rootObjectTag))) {
215         nsk_jvmti_setFailStatus();
216     }
217     NSK_DISPLAY2("        tag=%-5ld object=0x%p\n", (long)rootObjectTag, (void*)*rootObject);
218 
219     (*objectDescList)[0].tag = rootObjectTag;
220 
221     NSK_DISPLAY1("    reachable objects chain: %d objects\n", chainLength);
222     if (!getChainObjects(jvmti, jni, *rootObject,
223                                 reachableChainField, REACHABLE_CHAIN_FIELD_NAME,
224                                 tailField, TAIL_FIELD_NAME,
225                                 chainLength, (*objectDescList) + 1,
226                                 chainObjectTag, NSK_TRUE)) {
227         nsk_jvmti_setFailStatus();
228         return NSK_FALSE;
229     }
230 
231     NSK_DISPLAY1("    unreachable objects chain: %d objects\n", chainLength);
232     if (!getChainObjects(jvmti, jni, *rootObject,
233                                 unreachableChainField, UNREACHABLE_CHAIN_FIELD_NAME,
234                                 tailField, TAIL_FIELD_NAME,
235                                 chainLength, (*objectDescList) + 1 + chainLength,
236                                 chainObjectTag, NSK_FALSE)) {
237         nsk_jvmti_setFailStatus();
238         return NSK_FALSE;
239     }
240 
241     return NSK_TRUE;
242 }
243 
244 /** Check if tagged objects were iterated. */
checkTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int chainLength,ObjectDesc objectDescList[])245 static int checkTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni,
246                                 int chainLength, ObjectDesc objectDescList[]) {
247     int success = NSK_TRUE;
248     int i;
249 
250     NSK_DISPLAY0("Following tagged objects were iterated:\n");
251 
252     NSK_DISPLAY0("    root tested object:\n");
253     NSK_DISPLAY2("        tag=%-5ld found=%d times\n",
254                     (long)objectDescList[0].tag, objectDescList[0].found);
255 
256     NSK_DISPLAY0("    reachable objects:\n");
257     for (i = 0; i < chainLength; i++) {
258         NSK_DISPLAY2("        tag=%-5ld found=%d times\n",
259                         (long)objectDescList[i + 1].tag, objectDescList[i + 1].found);
260 
261         if (objectDescList[i + 1].found <= 0) {
262             NSK_COMPLAIN2("Reachable object was not iterated:\n"
263                           "#   tag:      %ld\n"
264                           "#   iterated: %d times\n",
265                             (long)objectDescList[i + 1].tag,
266                             objectDescList[i + 1].found);
267             nsk_jvmti_setFailStatus();
268         }
269     }
270 
271     NSK_DISPLAY0("    unreachable objects:\n");
272     for (i = 0; i < chainLength; i++) {
273         NSK_DISPLAY2("        tag=%-5ld found=%d times\n",
274                         (long)objectDescList[i + 1 + chainLength].tag,
275                         objectDescList[i + 1 + chainLength].found);
276 
277         if (objectDescList[i + 1 + chainLength].found > 0) {
278             NSK_COMPLAIN2("Unreachable object was iterated:\n"
279                           "#   tag:      %ld\n"
280                           "#   iterated: %d times\n",
281                             (long)objectDescList[i + 1 + chainLength].tag,
282                             objectDescList[i + 1 + chainLength].found);
283             nsk_jvmti_setFailStatus();
284         }
285     }
286 
287     return NSK_TRUE;
288 }
289 
290 /** Release references to the tested objects and free allocated memory. */
releaseTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int chainLength,ObjectDesc * objectDescList,jobject rootObject)291 static int releaseTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
292                                         ObjectDesc* objectDescList, jobject rootObject) {
293     if (rootObject != NULL) {
294         NSK_DISPLAY1("Release object reference to root tested object: 0x%p\n", rootObject);
295         NSK_TRACE(jni->DeleteGlobalRef(rootObject));
296     }
297 
298     if (objectDescList != NULL) {
299         NSK_DISPLAY1("Deallocate objects list: 0x%p\n", (void*)objectDescList);
300         if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)objectDescList))) {
301             nsk_jvmti_setFailStatus();
302         }
303     }
304 
305     return NSK_TRUE;
306 }
307 
308 /* ============================================================================= */
309 
310 /** objectReferenceCallback for heap iterator. */
311 jvmtiIterationControl JNICALL
objectReferenceCallback(jvmtiObjectReferenceKind reference_kind,jlong class_tag,jlong size,jlong * tag_ptr,jlong refferrer_tag,jint refferrer_index,void * user_data)312 objectReferenceCallback(jvmtiObjectReferenceKind reference_kind,
313                             jlong class_tag, jlong size, jlong* tag_ptr,
314                             jlong refferrer_tag, jint refferrer_index,
315                             void* user_data) {
316 
317     if (info & INFO_OBJREF) {
318         NSK_DISPLAY6("  objectReferenceCallback: ref_kind=%1d class_tag=%-3ld size=%-3ld"
319                         " *tag_ptr=%-5ld ref_tag=%-5ld ref_idx=%d\n",
320                         (int)reference_kind, (long)class_tag, (long)size,
321                         (long)(tag_ptr == NULL ? (jlong)0 : *tag_ptr),
322                         (long)refferrer_tag, (int)refferrer_index);
323     }
324 
325     if (tag_ptr == NULL) {
326         NSK_COMPLAIN6("NULL tag_ptr is passed to objectReferenceCallback:\n"
327                       "#   tag_ptr:        0x%p\n"
328                       "#   reference_kind: %d\n"
329                       "#   class_tag:      %ld\n"
330                       "#   size:           %ld\n"
331                       "#   refferrer_tag:  %ld\n"
332                       "#   refferrer_idx:  %d\n",
333                         (void*)tag_ptr,
334                         (int)reference_kind,
335                         (long)class_tag,
336                         (long)size,
337                         (long)refferrer_tag,
338                         (int)refferrer_index);
339         nsk_jvmti_setFailStatus();
340     }
341 
342     if (tag_ptr != NULL && *tag_ptr != 0) {
343         int found = 0;
344         int i;
345 
346         for (i = 0; i < objectsCount; i++) {
347             if (*tag_ptr == objectDescList[i].tag) {
348                 found++;
349                 objectDescList[i].found++;
350 
351                 if (*tag_ptr < 0) {
352                     NSK_COMPLAIN6("Unreachable tagged object is passed to objectReferenceCallback:\n"
353                                   "#   tag:            %ld\n"
354                                   "#   reference_kind: %d\n"
355                                   "#   class_tag:      %ld\n"
356                                   "#   size:           %ld\n"
357                                   "#   refferrer_tag:  %ld\n"
358                                   "#   refferrer_idx:  %d\n",
359                                     (long)*tag_ptr,
360                                     (int)reference_kind,
361                                     (long)class_tag,
362                                     (long)size,
363                                     (long)refferrer_tag,
364                                     (int)refferrer_index);
365                     nsk_jvmti_setFailStatus();
366                 }
367                 break;
368             }
369         }
370 
371         if (found <= 0) {
372             NSK_COMPLAIN6("Unknown tagged object is passed to objectReferenceCallback:\n"
373                           "#   tag:            %ld\n"
374                           "#   reference_kind: %d\n"
375                           "#   class_tag:      %ld\n"
376                           "#   size:           %ld\n"
377                           "#   refferrer_tag:  %ld\n"
378                           "#   refferrer_idx:  %d\n",
379                             (long)*tag_ptr,
380                             (int)reference_kind,
381                             (long)class_tag,
382                             (long)size,
383                             (long)refferrer_tag,
384                             (int)refferrer_index);
385             nsk_jvmti_setFailStatus();
386         }
387     }
388 
389     if (user_data != &fakeUserData && !userDataError) {
390        NSK_COMPLAIN2("Unexpected user_data is passed to objectReferenceCallback:\n"
391                       "#   expected:       0x%p\n"
392                       "#   actual:         0x%p\n",
393                       user_data,
394                       &fakeUserData);
395         nsk_jvmti_setFailStatus();
396         userDataError++;
397     }
398 
399     if (reference_kind == JVMTI_REFERENCE_CLASS)
400         return JVMTI_ITERATION_IGNORE;
401 
402     return JVMTI_ITERATION_CONTINUE;
403 }
404 
405 /* ============================================================================= */
406 
407 /** Agent algorithm. */
408 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * jni,void * arg)409 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
410     NSK_DISPLAY0("Wait for tested objects created\n");
411     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
412         return;
413 
414     {
415         jobject rootObject = NULL;
416 
417         NSK_DISPLAY0(">>> Obtain and tag tested objects from debugee class\n");
418         {
419             if (!NSK_VERIFY(getTestedObjects(jvmti, jni, chainLength,
420                                             &objectsCount, &objectDescList, &rootObject)))
421                 return;
422         }
423 
424         NSK_DISPLAY0(">>> Let debugee to clean links to unreachable objects\n");
425         {
426             if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
427                 return;
428             if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
429                 return;
430         }
431 
432         NSK_DISPLAY0(">>> Start iteration for root tested object\n");
433         {
434             if (!NSK_JVMTI_VERIFY(
435                     jvmti->IterateOverObjectsReachableFromObject(
436                         rootObject, objectReferenceCallback, &fakeUserData))) {
437                 nsk_jvmti_setFailStatus();
438                 return;
439             }
440         }
441 
442         NSK_DISPLAY0(">>> Check if reachable objects were iterated:\n");
443         {
444             if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
445                 nsk_jvmti_setFailStatus();
446             }
447         }
448 
449         NSK_DISPLAY0(">>> Clean used data\n");
450         {
451             if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, chainLength,
452                                                         objectDescList, rootObject)))
453                 return;
454         }
455     }
456 
457     NSK_DISPLAY0("Let debugee to finish\n");
458     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
459         return;
460 }
461 
462 /* ============================================================================= */
463 
464 /** Agent library initialization. */
465 #ifdef STATIC_BUILD
Agent_OnLoad_iterobjreachobj001(JavaVM * jvm,char * options,void * reserved)466 JNIEXPORT jint JNICALL Agent_OnLoad_iterobjreachobj001(JavaVM *jvm, char *options, void *reserved) {
467     return Agent_Initialize(jvm, options, reserved);
468 }
Agent_OnAttach_iterobjreachobj001(JavaVM * jvm,char * options,void * reserved)469 JNIEXPORT jint JNICALL Agent_OnAttach_iterobjreachobj001(JavaVM *jvm, char *options, void *reserved) {
470     return Agent_Initialize(jvm, options, reserved);
471 }
JNI_OnLoad_iterobjreachobj001(JavaVM * jvm,char * options,void * reserved)472 JNIEXPORT jint JNI_OnLoad_iterobjreachobj001(JavaVM *jvm, char *options, void *reserved) {
473     return JNI_VERSION_1_8;
474 }
475 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)476 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
477     jvmtiEnv* jvmti = NULL;
478 
479     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
480         return JNI_ERR;
481 
482     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
483 
484     {
485         const char* infoOpt = nsk_jvmti_findOptionValue("info");
486         if (infoOpt != NULL) {
487             if (strcmp(infoOpt, "none") == 0)
488                 info = INFO_NONE;
489             else if (strcmp(infoOpt, "all") == 0)
490                 info = INFO_ALL;
491             else if (strcmp(infoOpt, "objref") == 0)
492                 info = INFO_OBJREF;
493             else if (strcmp(infoOpt, "stackref") == 0)
494                 info = INFO_STACKREF;
495             else if (strcmp(infoOpt, "heaproot") == 0)
496                 info = INFO_HEAPROOT;
497             else if (strcmp(infoOpt, "heapobj") == 0)
498                 info = INFO_HEAPOBJ;
499             else {
500                 NSK_COMPLAIN1("Unknown option value: info=%s\n", infoOpt);
501                 return JNI_ERR;
502             }
503         }
504     }
505 
506     chainLength = nsk_jvmti_findOptionIntValue("objects", DEFAULT_CHAIN_LENGTH);
507     if (!NSK_VERIFY(chainLength > 0))
508         return JNI_ERR;
509 
510     if (!NSK_VERIFY((jvmti =
511             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
512         return JNI_ERR;
513 
514     {
515         jvmtiCapabilities caps;
516 
517         memset(&caps, 0, sizeof(caps));
518         caps.can_tag_objects = 1;
519         if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
520             return JNI_ERR;
521         }
522     }
523 
524     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
525         return JNI_ERR;
526 
527     return JNI_OK;
528 }
529 
530 /* ============================================================================= */
531 
532 }
533