1 /*
2  * Copyright (c) 2004, 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 #include "JVMTITools.h"
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /* ============================================================================= */
36 
37 /* scaffold objects */
38 static jvmtiEnv *jvmti = NULL;
39 static jlong timeout = 0;
40 static jrawMonitorID syncLock = NULL;
41 
42 /* constant names */
43 #define STEP_NUMBER 3
44 #define OBJECT_NUMBER 100
45 #define JVMTI_EVENT_COUNT   (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1)
46 
47 static int eventCount[JVMTI_EVENT_COUNT];
48 static int newEventCount[JVMTI_EVENT_COUNT];
49 
50 /* ============================================================================= */
51 
52 
53 /*
54  * Class:     nsk_jvmti_scenarios_events_EM02_em02t006
55  * Method:    setTag
56  * Signature: (Ljava/lang/Object;J)Z
57  */
58 JNIEXPORT jboolean JNICALL
Java_nsk_jvmti_scenarios_events_EM02_em02t006_setTag(JNIEnv * env,jobject this,jobject object,jlong tag)59 Java_nsk_jvmti_scenarios_events_EM02_em02t006_setTag(JNIEnv *env,
60                         jobject this, jobject object, jlong tag) {
61 
62     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, object, tag))) {
63         NSK_COMPLAIN0("TEST FAILED: unable to set tag for a tested object\n");
64         return NSK_FALSE;
65     }
66     return NSK_TRUE;
67 }
68 
69 static void
showEventStatistics(int step)70 showEventStatistics(int step) {
71     int i;
72     const char* str;
73     int *currentCounts = (step == 1) ? &eventCount[0] : &newEventCount[0];
74 
75     NSK_DISPLAY0("\n");
76     NSK_DISPLAY1("Event statistics for %d step:\n", step);
77     NSK_DISPLAY0("-----------------------------\n");
78     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
79         if (currentCounts[i] > 0) {
80             str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
81             NSK_DISPLAY2("%-40s %7d\n", str, currentCounts[i]);
82         }
83     }
84 }
85 
86 /* ========================================================================== */
87 
checkEvents(int step)88 int checkEvents(int step) {
89     int i;
90     jvmtiEvent curr;
91     int result = NSK_TRUE;
92     int *currentCounts;
93     int isExpected = 0;
94 
95     switch (step) {
96         case 1:
97             currentCounts = &eventCount[0];
98             break;
99 
100         case 2:
101         case 3:
102             currentCounts = &newEventCount[0];
103             break;
104 
105         default:
106             NSK_COMPLAIN1("Unexpected step no: %d\n", step);
107             return NSK_FALSE;
108     }
109 
110     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
111 
112         curr = i + JVMTI_MIN_EVENT_TYPE_VAL;
113 
114         switch (step) {
115             case 1:
116                 isExpected = ((curr == JVMTI_EVENT_OBJECT_FREE)
117                                 || (curr == JVMTI_EVENT_VM_INIT));
118                 break;
119 
120             case 2:
121                 isExpected = (curr == JVMTI_EVENT_OBJECT_FREE);
122                 break;
123 
124             case 3:
125                 isExpected = (curr == JVMTI_EVENT_VM_DEATH);
126                 break;
127         }
128 
129         if (isExpected) {
130             if (currentCounts[i] < 0 || currentCounts[i] > OBJECT_NUMBER) {
131                     NSK_COMPLAIN2("Unexpected events number %7d for %s\n\texpected value must be greater than 1\n",
132                                         currentCounts[i],
133                                         TranslateEvent(curr));
134                 result = NSK_FALSE;
135             }
136         } else {
137 
138             if (currentCounts[i] > 0) {
139                 NSK_COMPLAIN2("Unexpected event %s was sent %d times\n",
140                                     TranslateEvent(curr),
141                                     currentCounts[i]);
142                 result = NSK_FALSE;
143             }
144         }
145     }
146 
147     return result;
148 }
149 
150 static void
changeCount(jvmtiEvent event,int * currentCounts)151 changeCount(jvmtiEvent event, int *currentCounts) {
152 
153     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti, syncLock)))
154         nsk_jvmti_setFailStatus();
155 
156     currentCounts[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
157 
158     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti, syncLock)))
159         nsk_jvmti_setFailStatus();
160 
161 }
162 
163 /* ============================================================================= */
164 
165 /* callbacks */
166 JNIEXPORT void JNICALL
cbVMInit(jvmtiEnv * jvmti,JNIEnv * jni_env,jthread thread)167 cbVMInit(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread) {
168     changeCount(JVMTI_EVENT_VM_INIT, &eventCount[0]);
169 }
170 
171 JNIEXPORT void JNICALL
cbVMDeath(jvmtiEnv * jvmti,JNIEnv * jni_env)172 cbVMDeath(jvmtiEnv* jvmti, JNIEnv* jni_env) {
173     changeCount(JVMTI_EVENT_VM_DEATH, &newEventCount[0]);
174     showEventStatistics(STEP_NUMBER);
175     if (!checkEvents(STEP_NUMBER))
176         nsk_jvmti_setFailStatus();
177 
178     if (!NSK_JVMTI_VERIFY(
179             NSK_CPP_STUB2(DestroyRawMonitor, jvmti, syncLock)))
180         nsk_jvmti_setFailStatus();
181 
182 }
183 
184 void JNICALL
cbException(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jobject exception,jmethodID catch_method,jlocation catch_location)185 cbException(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
186                 jmethodID method, jlocation location, jobject exception,
187                 jmethodID catch_method, jlocation catch_location) {
188     changeCount(JVMTI_EVENT_EXCEPTION, &eventCount[0]);
189 }
190 
191 void JNICALL
cbExceptionCatch(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jobject exception)192 cbExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
193                 jmethodID method, jlocation location, jobject exception) {
194     changeCount(JVMTI_EVENT_EXCEPTION_CATCH, &eventCount[0]);
195 }
196 
197 void JNICALL
cbSingleStep(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location)198 cbSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
199                 jmethodID method, jlocation location) {
200     changeCount(JVMTI_EVENT_SINGLE_STEP, &eventCount[0]);
201 }
202 
203 void JNICALL
cbFramePop(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jboolean was_popped_by_exception)204 cbFramePop(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
205                 jmethodID method, jboolean was_popped_by_exception) {
206     changeCount(JVMTI_EVENT_FRAME_POP, &eventCount[0]);
207 }
208 
209 void JNICALL
cbBreakpoint(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location)210 cbBreakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
211                 jmethodID method, jlocation location) {
212     changeCount(JVMTI_EVENT_BREAKPOINT, &eventCount[0]);
213 }
214 
215 void JNICALL
cbFieldAccess(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jclass field_klass,jobject object,jfieldID field)216 cbFieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
217                 jmethodID method, jlocation location, jclass field_klass,
218                 jobject object, jfieldID field) {
219     changeCount(JVMTI_EVENT_FIELD_ACCESS, &eventCount[0]);
220 }
221 
222 void JNICALL
cbFieldModification(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jclass field_klass,jobject object,jfieldID field,char signature_type,jvalue new_value)223 cbFieldModification(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
224                 jmethodID method, jlocation location, jclass field_klass,
225                 jobject object, jfieldID field, char signature_type,
226                 jvalue new_value) {
227     changeCount(JVMTI_EVENT_FIELD_MODIFICATION, &eventCount[0]);
228 }
229 
230 void JNICALL
cbMethodEntry(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method)231 cbMethodEntry(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
232                 jmethodID method) {
233     changeCount(JVMTI_EVENT_METHOD_ENTRY, &eventCount[0]);
234 }
235 
236 void JNICALL
cbMethodExit(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jboolean was_popped_by_exception,jvalue return_value)237 cbMethodExit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
238                 jmethodID method, jboolean was_popped_by_exception,
239                 jvalue return_value) {
240     changeCount(JVMTI_EVENT_METHOD_EXIT, &eventCount[0]);
241 }
242 
243 void JNICALL
cbNativeMethodBind(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,void * address,void ** new_address_ptr)244 cbNativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv* jni_env,jthread thread,
245                 jmethodID method, void* address, void** new_address_ptr) {
246     changeCount(JVMTI_EVENT_NATIVE_METHOD_BIND, &eventCount[0]);
247 }
248 
249 void JNICALL
cbMonitorWait(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object,jlong tout)250 cbMonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
251                     jobject object, jlong tout) {
252 
253     changeCount(JVMTI_EVENT_MONITOR_WAIT, &eventCount[0]);
254 }
255 
256 void JNICALL
cbMonitorWaited(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object,jboolean timed_out)257 cbMonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
258                     jobject object, jboolean timed_out) {
259 
260     changeCount(JVMTI_EVENT_MONITOR_WAITED, &eventCount[0]);
261 }
262 
263 JNIEXPORT void JNICALL
cbMonitorContendedEnter(jvmtiEnv * jvmti,JNIEnv * jni_env,jthread thread,jobject object)264 cbMonitorContendedEnter(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread,
265                             jobject object) {
266 
267     changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTER, &eventCount[0]);
268 }
269 
270 void JNICALL
cbMonitorContendedEntered(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object)271 cbMonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
272                             jobject object) {
273 
274     changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, &eventCount[0]);
275 }
276 
277 void JNICALL
cbCompiledMethodLoad(jvmtiEnv * jvmti_env,jmethodID method,jint code_size,const void * code_addr,jint map_length,const jvmtiAddrLocationMap * map,const void * compile_info)278 cbCompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size,
279                 const void* code_addr, jint map_length,
280                 const jvmtiAddrLocationMap* map, const void* compile_info) {
281     changeCount(JVMTI_EVENT_COMPILED_METHOD_LOAD, &eventCount[0]);
282 }
283 
284 void JNICALL
cbCompiledMethodUnload(jvmtiEnv * jvmti_env,jmethodID method,const void * code_addr)285 cbCompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method,
286                 const void* code_addr) {
287     changeCount(JVMTI_EVENT_COMPILED_METHOD_UNLOAD, &eventCount[0]);
288 }
289 
290 void JNICALL
cbGarbageCollectionStart(jvmtiEnv * jvmti_env)291 cbGarbageCollectionStart(jvmtiEnv *jvmti_env) {
292     changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_START, &eventCount[0]);
293 }
294 
295 void JNICALL
cbGarbageCollectionFinish(jvmtiEnv * jvmti_env)296 cbGarbageCollectionFinish(jvmtiEnv *jvmti_env) {
297     changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, &eventCount[0]);
298 }
299 
300 void JNICALL
cbObjectFree(jvmtiEnv * jvmti_env,jlong tag)301 cbObjectFree(jvmtiEnv *jvmti_env, jlong tag) {
302 
303     changeCount(JVMTI_EVENT_OBJECT_FREE, &eventCount[0]);
304     if (tag < 1 || tag > OBJECT_NUMBER) {
305         NSK_COMPLAIN1("Unexpected tag value %lld\n", tag);
306         nsk_jvmti_setFailStatus();
307     }
308 }
309 
310 void JNICALL
cbNewObjectFree(jvmtiEnv * jvmti_env,jlong tag)311 cbNewObjectFree(jvmtiEnv *jvmti_env, jlong tag) {
312 
313     changeCount(JVMTI_EVENT_OBJECT_FREE, &newEventCount[0]);
314     if (tag < 1 || tag > OBJECT_NUMBER) {
315         NSK_COMPLAIN1("Unexpected tag value %lld\n", tag);
316         nsk_jvmti_setFailStatus();
317     }
318 }
319 
320 void JNICALL
cbVMObjectAlloc(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object,jclass object_klass,jlong size)321 cbVMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
322                     jobject object, jclass object_klass, jlong size) {
323 
324     changeCount(JVMTI_EVENT_VM_OBJECT_ALLOC, &eventCount[0]);
325 }
326 
327 /* ============================================================================= */
328 
enableEvent(jvmtiEvent event)329 static int enableEvent(jvmtiEvent event) {
330 
331     if (nsk_jvmti_isOptionalEvent(event)
332             && (event != JVMTI_EVENT_OBJECT_FREE)) {
333         if (!NSK_JVMTI_VERIFY_CODE(JVMTI_ERROR_MUST_POSSESS_CAPABILITY,
334                 NSK_CPP_STUB4(SetEventNotificationMode, jvmti,
335                     JVMTI_ENABLE, event, NULL))) {
336             NSK_COMPLAIN1("Unexpected error enabling %s\n",
337                 TranslateEvent(event));
338             return NSK_FALSE;
339         }
340     } else {
341         if (!NSK_JVMTI_VERIFY(
342                 NSK_CPP_STUB4(SetEventNotificationMode, jvmti,
343                     JVMTI_ENABLE, event, NULL))) {
344             NSK_COMPLAIN1("Unexpected error enabling %s\n",
345                 TranslateEvent(event));
346             return NSK_FALSE;
347         }
348     }
349 
350     return NSK_TRUE;
351 }
352 
353 /**
354  * Enable or disable tested events.
355  */
enableEventList()356 static int enableEventList() {
357 
358     int i, result;
359 
360     result = enableEvent(JVMTI_EVENT_VM_INIT);
361 
362     result = result && enableEvent(JVMTI_EVENT_VM_DEATH);
363 
364     /* enabling optional events */
365     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
366         jvmtiEvent event = (jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL);
367 
368         if (nsk_jvmti_isOptionalEvent(event))
369             result = result && enableEvent(event);
370     }
371 
372     if (result == NSK_FALSE) {
373         nsk_jvmti_setFailStatus();
374         return NSK_FALSE;
375     }
376 
377     return NSK_TRUE;
378 }
379 
380 /* ============================================================================= */
381 
382 static int
setCallBacks(int step)383 setCallBacks(int step) {
384 
385     int i;
386 
387     jvmtiEventCallbacks eventCallbacks;
388     memset(&eventCallbacks, 0, sizeof(eventCallbacks));
389 
390     switch (step) {
391         case 1:
392             for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
393                 eventCount[i] = 0;
394             }
395 
396             eventCallbacks.VMInit                    = cbVMInit;
397             eventCallbacks.Exception                 = cbException;
398             eventCallbacks.ExceptionCatch            = cbExceptionCatch;
399             eventCallbacks.SingleStep                = cbSingleStep;
400             eventCallbacks.FramePop                  = cbFramePop;
401             eventCallbacks.Breakpoint                = cbBreakpoint;
402             eventCallbacks.FieldAccess               = cbFieldAccess;
403             eventCallbacks.FieldModification         = cbFieldModification;
404             eventCallbacks.MethodEntry               = cbMethodEntry;
405             eventCallbacks.MethodExit                = cbMethodExit;
406             eventCallbacks.NativeMethodBind          = cbNativeMethodBind;
407             eventCallbacks.CompiledMethodLoad        = cbCompiledMethodLoad;
408             eventCallbacks.CompiledMethodUnload      = cbCompiledMethodUnload;
409             eventCallbacks.MonitorWait               = cbMonitorWait;
410             eventCallbacks.MonitorWaited             = cbMonitorWaited;
411             eventCallbacks.MonitorContendedEnter     = cbMonitorContendedEnter;
412             eventCallbacks.MonitorContendedEntered   = cbMonitorContendedEntered;
413             eventCallbacks.GarbageCollectionStart    = cbGarbageCollectionStart;
414             eventCallbacks.GarbageCollectionFinish   = cbGarbageCollectionFinish;
415             eventCallbacks.ObjectFree                = cbObjectFree;
416             eventCallbacks.VMObjectAlloc             = cbVMObjectAlloc;
417             break;
418 
419         case 2:
420             for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
421                 newEventCount[i] = 0;
422             }
423 
424             eventCallbacks.ObjectFree                = cbNewObjectFree;
425             break;
426 
427         case 3:
428             for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
429                 newEventCount[i] = 0;
430             }
431 
432             eventCallbacks.VMDeath                   = cbVMDeath;
433             break;
434 
435     }
436     if (!NSK_JVMTI_VERIFY(
437             NSK_CPP_STUB3(SetEventCallbacks, jvmti,
438                                 &eventCallbacks,
439                                 sizeof(eventCallbacks))))
440         return NSK_FALSE;
441 
442     return NSK_TRUE;
443 }
444 
445 /* ============================================================================= */
446 
447 /** Agent algorithm. */
448 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * agentJNI,void * arg)449 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
450 
451     int i;
452 
453     for (i = 1; i <= STEP_NUMBER; i++) {
454 
455         if (!nsk_jvmti_waitForSync(timeout))
456             return;
457 
458         NSK_DISPLAY0("Check received events\n");
459 
460         if (i < STEP_NUMBER) {
461             showEventStatistics(i);
462             if (!checkEvents(i))
463                 nsk_jvmti_setFailStatus();
464 
465             if (!setCallBacks(i + 1)) {
466                 return;
467             }
468         }
469 
470         if (!nsk_jvmti_resumeSync())
471             return;
472     }
473 
474 }
475 
476 /* ============================================================================= */
477 
478 /** Agent library initialization. */
479 #ifdef STATIC_BUILD
Agent_OnLoad_em02t006(JavaVM * jvm,char * options,void * reserved)480 JNIEXPORT jint JNICALL Agent_OnLoad_em02t006(JavaVM *jvm, char *options, void *reserved) {
481     return Agent_Initialize(jvm, options, reserved);
482 }
Agent_OnAttach_em02t006(JavaVM * jvm,char * options,void * reserved)483 JNIEXPORT jint JNICALL Agent_OnAttach_em02t006(JavaVM *jvm, char *options, void *reserved) {
484     return Agent_Initialize(jvm, options, reserved);
485 }
JNI_OnLoad_em02t006(JavaVM * jvm,char * options,void * reserved)486 JNIEXPORT jint JNI_OnLoad_em02t006(JavaVM *jvm, char *options, void *reserved) {
487     return JNI_VERSION_1_8;
488 }
489 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)490 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
491 
492     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
493         return JNI_ERR;
494 
495     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
496 
497     if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
498         return JNI_ERR;
499 
500     if (!NSK_JVMTI_VERIFY(
501             NSK_CPP_STUB3(CreateRawMonitor, jvmti, "_syncLock", &syncLock))) {
502         nsk_jvmti_setFailStatus();
503         return JNI_ERR;
504     }
505 
506     {
507         jvmtiCapabilities caps;
508         memset(&caps, 0, sizeof(caps));
509 
510         caps.can_tag_objects = 1;
511         caps.can_generate_object_free_events = 1;
512         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps)))
513             return JNI_ERR;
514     }
515 
516     if (!setCallBacks(1)) {
517         return JNI_ERR;
518     }
519 
520     if (!enableEventList()) {
521         return JNI_ERR;
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 #ifdef __cplusplus
534 }
535 #endif
536