1 | /* |
2 | * Copyright (c) 1997, 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. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle in the LICENSE file that accompanied this code. |
10 | * |
11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | * version 2 for more details (a copy is included in the LICENSE file that |
15 | * accompanied this code). |
16 | * |
17 | * You should have received a copy of the GNU General Public License version |
18 | * 2 along with this work; if not, write to the Free Software Foundation, |
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
20 | * |
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * questions. |
24 | */ |
25 | |
26 | #ifndef JNI_UTIL_H |
27 | #define JNI_UTIL_H |
28 | |
29 | #include "jni.h" |
30 | #include "jlong.h" |
31 | |
32 | #ifdef __cplusplus |
33 | extern "C" { |
34 | #endif |
35 | |
36 | /* |
37 | * This file contains utility functions that can be implemented in pure JNI. |
38 | * |
39 | * Caution: Callers of functions declared in this file should be |
40 | * particularly aware of the fact that these functions are convenience |
41 | * functions, and as such are often compound operations, each one of |
42 | * which may throw an exception. Therefore, the functions this file |
43 | * will often return silently if an exception has occurred, and callers |
44 | * must check for exception themselves. |
45 | */ |
46 | |
47 | /* Throw a Java exception by name. Similar to SignalError. */ |
48 | JNIEXPORT void JNICALL |
49 | JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg); |
50 | |
51 | /* Throw common exceptions */ |
52 | JNIEXPORT void JNICALL |
53 | JNU_ThrowNullPointerException(JNIEnv *env, const char *msg); |
54 | |
55 | JNIEXPORT void JNICALL |
56 | JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg); |
57 | |
58 | JNIEXPORT void JNICALL |
59 | JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg); |
60 | |
61 | JNIEXPORT void JNICALL |
62 | JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg); |
63 | |
64 | JNIEXPORT void JNICALL |
65 | JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg); |
66 | |
67 | JNIEXPORT void JNICALL |
68 | JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg); |
69 | |
70 | JNIEXPORT void JNICALL |
71 | JNU_ThrowInternalError(JNIEnv *env, const char *msg); |
72 | |
73 | JNIEXPORT void JNICALL |
74 | JNU_ThrowIOException(JNIEnv *env, const char *msg); |
75 | |
76 | JNIEXPORT void JNICALL |
77 | JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg); |
78 | |
79 | JNIEXPORT void JNICALL |
80 | JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg); |
81 | |
82 | JNIEXPORT void JNICALL |
83 | JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg); |
84 | |
85 | JNIEXPORT void JNICALL |
86 | JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg); |
87 | |
88 | JNIEXPORT void JNICALL |
89 | JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg); |
90 | |
91 | JNIEXPORT void JNICALL |
92 | JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg); |
93 | |
94 | JNIEXPORT void JNICALL |
95 | JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg); |
96 | |
97 | JNIEXPORT void JNICALL |
98 | JNU_ThrowInstantiationException(JNIEnv *env, const char *msg); |
99 | |
100 | /* Throw an exception by name, using the string returned by |
101 | * getLastErrorString for the detail string. If the last-error |
102 | * string is NULL, use the given default detail string. |
103 | */ |
104 | JNIEXPORT void JNICALL |
105 | JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name, |
106 | const char *defaultDetail); |
107 | |
108 | /* Throw an exception by name, using a given message and the string |
109 | * returned by getLastErrorString to construct the detail string. |
110 | */ |
111 | JNIEXPORT void JNICALL |
112 | JNU_ThrowByNameWithMessageAndLastError |
113 | (JNIEnv *env, const char *name, const char *message); |
114 | |
115 | /* Throw an IOException, using the last-error string for the detail |
116 | * string. If the last-error string is NULL, use the given default |
117 | * detail string. |
118 | */ |
119 | JNIEXPORT void JNICALL |
120 | JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail); |
121 | |
122 | /* Convert between Java strings and i18n C strings */ |
123 | JNIEXPORT jstring |
124 | NewStringPlatform(JNIEnv *env, const char *str); |
125 | |
126 | JNIEXPORT const char * |
127 | GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy); |
128 | |
129 | JNIEXPORT jstring JNICALL |
130 | JNU_NewStringPlatform(JNIEnv *env, const char *str); |
131 | |
132 | JNIEXPORT const char * JNICALL |
133 | JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy); |
134 | |
135 | JNIEXPORT void JNICALL |
136 | JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str); |
137 | |
138 | /* Class constants */ |
139 | JNIEXPORT jclass JNICALL |
140 | JNU_ClassString(JNIEnv *env); |
141 | |
142 | JNIEXPORT jclass JNICALL |
143 | JNU_ClassClass(JNIEnv *env); |
144 | |
145 | JNIEXPORT jclass JNICALL |
146 | JNU_ClassObject(JNIEnv *env); |
147 | |
148 | JNIEXPORT jclass JNICALL |
149 | JNU_ClassThrowable(JNIEnv *env); |
150 | |
151 | /* Copy count number of arguments from src to dst. Array bounds |
152 | * and ArrayStoreException are checked. |
153 | */ |
154 | JNIEXPORT jint JNICALL |
155 | JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, |
156 | jint count); |
157 | |
158 | /* Invoke a object-returning static method, based on class name, |
159 | * method name, and signature string. |
160 | * |
161 | * The caller should check for exceptions by setting hasException |
162 | * argument. If the caller is not interested in whether an exception |
163 | * has occurred, pass in NULL. |
164 | */ |
165 | JNIEXPORT jvalue JNICALL |
166 | JNU_CallStaticMethodByName(JNIEnv *env, |
167 | jboolean *hasException, |
168 | const char *class_name, |
169 | const char *name, |
170 | const char *signature, |
171 | ...); |
172 | |
173 | /* Invoke an instance method by name. |
174 | */ |
175 | JNIEXPORT jvalue JNICALL |
176 | JNU_CallMethodByName(JNIEnv *env, |
177 | jboolean *hasException, |
178 | jobject obj, |
179 | const char *name, |
180 | const char *signature, |
181 | ...); |
182 | |
183 | JNIEXPORT jvalue JNICALL |
184 | JNU_CallMethodByNameV(JNIEnv *env, |
185 | jboolean *hasException, |
186 | jobject obj, |
187 | const char *name, |
188 | const char *signature, |
189 | va_list args); |
190 | |
191 | /* Construct a new object of class, specifying the class by name, |
192 | * and specififying which constructor to run and what arguments to |
193 | * pass to it. |
194 | * |
195 | * The method will return an initialized instance if successful. |
196 | * It will return NULL if an error has occurred (for example if |
197 | * it ran out of memory) and the appropriate Java exception will |
198 | * have been thrown. |
199 | */ |
200 | JNIEXPORT jobject JNICALL |
201 | JNU_NewObjectByName(JNIEnv *env, const char *class_name, |
202 | const char *constructor_sig, ...); |
203 | |
204 | /* returns: |
205 | * 0: object is not an instance of the class named by classname. |
206 | * 1: object is an instance of the class named by classname. |
207 | * -1: the class named by classname cannot be found. An exception |
208 | * has been thrown. |
209 | */ |
210 | JNIEXPORT jint JNICALL |
211 | JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char *classname); |
212 | |
213 | |
214 | /* Get or set class and instance fields. |
215 | * Note that set functions take a variable number of arguments, |
216 | * but only one argument of the appropriate type can be passed. |
217 | * For example, to set an integer field i to 100: |
218 | * |
219 | * JNU_SetFieldByName(env, &exc, obj, "i", "I", 100); |
220 | * |
221 | * To set a float field f to 12.3: |
222 | * |
223 | * JNU_SetFieldByName(env, &exc, obj, "f", "F", 12.3); |
224 | * |
225 | * The caller should check for exceptions by setting hasException |
226 | * argument. If the caller is not interested in whether an exception |
227 | * has occurred, pass in NULL. |
228 | */ |
229 | JNIEXPORT jvalue JNICALL |
230 | JNU_GetFieldByName(JNIEnv *env, |
231 | jboolean *hasException, |
232 | jobject obj, |
233 | const char *name, |
234 | const char *sig); |
235 | JNIEXPORT void JNICALL |
236 | JNU_SetFieldByName(JNIEnv *env, |
237 | jboolean *hasException, |
238 | jobject obj, |
239 | const char *name, |
240 | const char *sig, |
241 | ...); |
242 | |
243 | JNIEXPORT jvalue JNICALL |
244 | JNU_GetStaticFieldByName(JNIEnv *env, |
245 | jboolean *hasException, |
246 | const char *classname, |
247 | const char *name, |
248 | const char *sig); |
249 | JNIEXPORT void JNICALL |
250 | JNU_SetStaticFieldByName(JNIEnv *env, |
251 | jboolean *hasException, |
252 | const char *classname, |
253 | const char *name, |
254 | const char *sig, |
255 | ...); |
256 | |
257 | |
258 | /* |
259 | * Calls the .equals method. |
260 | */ |
261 | JNIEXPORT jboolean JNICALL |
262 | JNU_Equals(JNIEnv *env, jobject object1, jobject object2); |
263 | |
264 | |
265 | /************************************************************************ |
266 | * Thread calls |
267 | * |
268 | * Convenience thread-related calls on the java.lang.Object class. |
269 | */ |
270 | |
271 | JNIEXPORT void JNICALL |
272 | JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout); |
273 | |
274 | JNIEXPORT void JNICALL |
275 | JNU_Notify(JNIEnv *env, jobject object); |
276 | |
277 | JNIEXPORT void JNICALL |
278 | JNU_NotifyAll(JNIEnv *env, jobject object); |
279 | |
280 | |
281 | /************************************************************************ |
282 | * Miscellaneous utilities used by the class libraries |
283 | */ |
284 | |
285 | #define IS_NULL(obj) ((obj) == NULL) |
286 | #define JNU_IsNull(env,obj) ((obj) == NULL) |
287 | |
288 | /************************************************************************ |
289 | * Miscellaneous utilities used by the class libraries to return from |
290 | * a function if a value is NULL or an exception is pending. |
291 | */ |
292 | |
293 | #define CHECK_NULL(x) \ |
294 | do { \ |
295 | if ((x) == NULL) { \ |
296 | return; \ |
297 | } \ |
298 | } while (0) \ |
299 | |
300 | #define CHECK_NULL_THROW_NPE(env, x, msg) \ |
301 | do { \ |
302 | if ((x) == NULL) { \ |
303 | JNU_ThrowNullPointerException((env), (msg));\ |
304 | return; \ |
305 | } \ |
306 | } while(0) \ |
307 | |
308 | #define CHECK_NULL_THROW_NPE_RETURN(env, x, msg, z)\ |
309 | do { \ |
310 | if ((x) == NULL) { \ |
311 | JNU_ThrowNullPointerException((env), (msg));\ |
312 | return (z); \ |
313 | } \ |
314 | } while(0) \ |
315 | |
316 | #define CHECK_NULL_RETURN(x, y) \ |
317 | do { \ |
318 | if ((x) == NULL) { \ |
319 | return (y); \ |
320 | } \ |
321 | } while (0) \ |
322 | |
323 | #ifdef __cplusplus |
324 | #define JNU_CHECK_EXCEPTION(env) \ |
325 | do { \ |
326 | if ((env)->ExceptionCheck()) { \ |
327 | return; \ |
328 | } \ |
329 | } while (0) \ |
330 | |
331 | #define JNU_CHECK_EXCEPTION_RETURN(env, y) \ |
332 | do { \ |
333 | if ((env)->ExceptionCheck()) { \ |
334 | return (y); \ |
335 | } \ |
336 | } while (0) |
337 | #else |
338 | #define JNU_CHECK_EXCEPTION(env) \ |
339 | do { \ |
340 | if ((*env)->ExceptionCheck(env)) { \ |
341 | return; \ |
342 | } \ |
343 | } while (0) \ |
344 | |
345 | #define JNU_CHECK_EXCEPTION_RETURN(env, y) \ |
346 | do { \ |
347 | if ((*env)->ExceptionCheck(env)) { \ |
348 | return (y); \ |
349 | } \ |
350 | } while (0) |
351 | #endif /* __cplusplus */ |
352 | /************************************************************************ |
353 | * Debugging utilities |
354 | */ |
355 | |
356 | JNIEXPORT void JNICALL |
357 | JNU_PrintString(JNIEnv *env, char *hdr, jstring string); |
358 | |
359 | JNIEXPORT void JNICALL |
360 | JNU_PrintClass(JNIEnv *env, char *hdr, jobject object); |
361 | |
362 | JNIEXPORT jstring JNICALL |
363 | JNU_ToString(JNIEnv *env, jobject object); |
364 | |
365 | /* |
366 | * Package shorthand for use by native libraries |
367 | */ |
368 | #define JNU_JAVAPKG "java/lang/" |
369 | #define JNU_JAVAIOPKG "java/io/" |
370 | #define JNU_JAVANETPKG "java/net/" |
371 | |
372 | /* |
373 | * Check if the current thread is attached to the VM, and returns |
374 | * the JNIEnv of the specified version if the thread is attached. |
375 | * |
376 | * If the current thread is not attached, this function returns 0. |
377 | * |
378 | * If the current thread is attached, this function returns the |
379 | * JNI environment, or returns (void *)JNI_ERR if the specified |
380 | * version is not supported. |
381 | */ |
382 | JNIEXPORT void * JNICALL |
383 | JNU_GetEnv(JavaVM *vm, jint version); |
384 | |
385 | /* |
386 | * Warning free access to pointers stored in Java long fields. |
387 | */ |
388 | #define JNU_GetLongFieldAsPtr(env,obj,id) \ |
389 | (jlong_to_ptr((*(env))->GetLongField((env),(obj),(id)))) |
390 | #define JNU_SetLongFieldFromPtr(env,obj,id,val) \ |
391 | (*(env))->SetLongField((env),(obj),(id),ptr_to_jlong(val)) |
392 | |
393 | /* |
394 | * Internal use only. |
395 | */ |
396 | enum { |
397 | NO_ENCODING_YET = 0, /* "sun.jnu.encoding" not yet set */ |
398 | NO_FAST_ENCODING, /* Platform encoding is not fast */ |
399 | FAST_8859_1, /* ISO-8859-1 */ |
400 | FAST_CP1252, /* MS-DOS Cp1252 */ |
401 | FAST_646_US, /* US-ASCII : ISO646-US */ |
402 | FAST_UTF_8 |
403 | }; |
404 | |
405 | int getFastEncoding(); |
406 | |
407 | JNIEXPORT void InitializeEncoding(JNIEnv *env, const char *name); |
408 | |
409 | void* getProcessHandle(); |
410 | |
411 | void buildJniFunctionName(const char *sym, const char *cname, |
412 | char *jniEntryName); |
413 | |
414 | JNIEXPORT size_t JNICALL |
415 | getLastErrorString(char *buf, size_t len); |
416 | |
417 | JNIEXPORT int JNICALL |
418 | getErrorString(int err, char *buf, size_t len); |
419 | |
420 | #ifdef STATIC_BUILD |
421 | /* Macros for handling declaration of static/dynamic |
422 | * JNI library Load/Unload functions |
423 | * |
424 | * Use DEF_JNI_On{Un}Load when you want a static and non-static entry points. |
425 | * Use DEF_STATIC_JNI_On{Un}Load when you only want a static one. |
426 | * |
427 | * LIBRARY_NAME must be set to the name of the library |
428 | */ |
429 | |
430 | /* These three macros are needed to get proper concatenation of |
431 | * the LIBRARY_NAME |
432 | * |
433 | * NOTE: LIBRARY_NAME must be set for static builds. |
434 | */ |
435 | #define ADD_LIB_NAME3(name, lib) name ## lib |
436 | #define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib) |
437 | #define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME) |
438 | |
439 | #define DEF_JNI_OnLoad \ |
440 | ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) \ |
441 | { \ |
442 | jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)(JavaVM *vm, void *reserved); \ |
443 | ADD_LIB_NAME(JNI_OnLoad_dynamic_)(vm, reserved); \ |
444 | return JNI_VERSION_1_8; \ |
445 | } \ |
446 | jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_) |
447 | |
448 | #define DEF_STATIC_JNI_OnLoad \ |
449 | JNIEXPORT jint JNICALL ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) { \ |
450 | return JNI_VERSION_1_8; \ |
451 | } |
452 | |
453 | #define DEF_JNI_OnUnload \ |
454 | ADD_LIB_NAME(JNI_OnUnload_)(JavaVM *vm, void *reserved) \ |
455 | { \ |
456 | void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)(JavaVM *vm, void *reserved); \ |
457 | ADD_LIB_NAME(JNI_OnUnload_dynamic_)(vm, reserved); \ |
458 | } \ |
459 | void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_) |
460 | |
461 | #define DEF_STATIC_JNI_OnUnload \ |
462 | ADD_LIB_NAME(JNI_OnUnload_) |
463 | |
464 | #else |
465 | |
466 | #define DEF_JNI_OnLoad JNI_OnLoad |
467 | #define DEF_STATIC_JNI_OnLoad |
468 | #define DEF_JNI_OnUnload JNI_OnUnload |
469 | #define DEF_STATIC_JNI_OnUnload |
470 | #endif |
471 | |
472 | #ifdef STATIC_BUILD |
473 | /* Macros for handling declaration of static/dynamic |
474 | * Agent library Load/Attach/Unload functions |
475 | * |
476 | * Use DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload |
477 | * when you want both static and non-static entry points. |
478 | * Use DEF_STATIC_Agent_OnLoad, DEF_STATIC_Agent_OnAttach or |
479 | * DEF_STATIC_Agent_OnUnload when you only want a static one. |
480 | * |
481 | * LIBRARY_NAME must be set to the name of the library for static builds. |
482 | */ |
483 | |
484 | #define DEF_Agent_OnLoad \ |
485 | ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \ |
486 | { \ |
487 | jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \ |
488 | return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \ |
489 | } \ |
490 | jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_) |
491 | |
492 | #define DEF_STATIC_Agent_OnLoad \ |
493 | JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \ |
494 | return JNI_FALSE; \ |
495 | } |
496 | |
497 | #define DEF_Agent_OnAttach \ |
498 | ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \ |
499 | { \ |
500 | jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \ |
501 | return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \ |
502 | } \ |
503 | jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_) |
504 | |
505 | #define DEF_STATIC_Agent_OnAttach \ |
506 | JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \ |
507 | return JNI_FALSE; \ |
508 | } |
509 | |
510 | #define DEF_Agent_OnUnload \ |
511 | ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \ |
512 | { \ |
513 | void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \ |
514 | ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \ |
515 | } \ |
516 | void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_) |
517 | |
518 | #define DEF_STATIC_Agent_OnUnload \ |
519 | ADD_LIB_NAME(Agent_OnUnload_) |
520 | |
521 | #else |
522 | #define DEF_Agent_OnLoad Agent_OnLoad |
523 | #define DEF_Agent_OnAttach Agent_OnAttach |
524 | #define DEF_Agent_OnUnload Agent_OnUnload |
525 | #define DEF_STATIC_Agent_OnLoad |
526 | #define DEF_STATIC_Agent_OnAttach |
527 | #define DEF_STATIC_Agent_OnUnload |
528 | #endif |
529 | |
530 | #ifdef __cplusplus |
531 | } /* extern "C" */ |
532 | #endif /* __cplusplus */ |
533 | |
534 | #endif /* JNI_UTIL_H */ |
535 | |