1 /*
2  * Copyright (c) 1997, 2020, 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_ThrowInternalError(JNIEnv *env, const char *msg);
66 
67 JNIEXPORT void JNICALL
68 JNU_ThrowIOException(JNIEnv *env, const char *msg);
69 
70 JNIEXPORT void JNICALL
71 JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg);
72 
73 /* Throw an exception by name, using the string returned by
74  * getLastErrorString for the detail string. If the last-error
75  * string is NULL, use the given default detail string.
76  */
77 JNIEXPORT void JNICALL
78 JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
79                              const char *defaultDetail);
80 
81 /* Throw an exception by name, using a given message and the string
82  * returned by getLastErrorString to construct the detail string.
83  */
84 JNIEXPORT void JNICALL
85 JNU_ThrowByNameWithMessageAndLastError
86   (JNIEnv *env, const char *name, const char *message);
87 
88 /* Throw an IOException, using the last-error string for the detail
89  * string. If the last-error string is NULL, use the given default
90  * detail string.
91  */
92 JNIEXPORT void JNICALL
93 JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail);
94 
95 /* Convert between Java strings and i18n C strings */
96 JNIEXPORT const char *
97 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
98 
99 JNIEXPORT jstring JNICALL
100 JNU_NewStringPlatform(JNIEnv *env, const char *str);
101 
102 JNIEXPORT const char * JNICALL
103 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
104 
105 JNIEXPORT void JNICALL
106 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str);
107 
108 /* Class constants */
109 JNIEXPORT jclass JNICALL
110 JNU_ClassString(JNIEnv *env);
111 
112 /* Copy count number of arguments from src to dst. Array bounds
113  * and ArrayStoreException are checked.
114  */
115 JNIEXPORT jint JNICALL
116 JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
117                     jint count);
118 
119 /* Invoke a object-returning static method, based on class name,
120  * method name, and signature string.
121  *
122  * The caller should check for exceptions by setting hasException
123  * argument. If the caller is not interested in whether an exception
124  * has occurred, pass in NULL.
125  */
126 JNIEXPORT jvalue JNICALL
127 JNU_CallStaticMethodByName(JNIEnv *env,
128                            jboolean *hasException,
129                            const char *class_name,
130                            const char *name,
131                            const char *signature,
132                            ...);
133 
134 /* Invoke an instance method by name.
135  */
136 JNIEXPORT jvalue JNICALL
137 JNU_CallMethodByName(JNIEnv *env,
138                      jboolean *hasException,
139                      jobject obj,
140                      const char *name,
141                      const char *signature,
142                      ...);
143 
144 JNIEXPORT jvalue JNICALL
145 JNU_CallMethodByNameV(JNIEnv *env,
146                       jboolean *hasException,
147                       jobject obj,
148                       const char *name,
149                       const char *signature,
150                       va_list args);
151 
152 /* Construct a new object of class, specifying the class by name,
153  * and specififying which constructor to run and what arguments to
154  * pass to it.
155  *
156  * The method will return an initialized instance if successful.
157  * It will return NULL if an error has occurred (for example if
158  * it ran out of memory) and the appropriate Java exception will
159  * have been thrown.
160  */
161 JNIEXPORT jobject JNICALL
162 JNU_NewObjectByName(JNIEnv *env, const char *class_name,
163                     const char *constructor_sig, ...);
164 
165 /* returns:
166  * 0: object is not an instance of the class named by classname.
167  * 1: object is an instance of the class named by classname.
168  * -1: the class named by classname cannot be found. An exception
169  * has been thrown.
170  */
171 JNIEXPORT jint JNICALL
172 JNU_IsInstanceOfByName(JNIEnv *env, jobject object, const char *classname);
173 
174 
175 /* Get or set class and instance fields.
176  * Note that set functions take a variable number of arguments,
177  * but only one argument of the appropriate type can be passed.
178  * For example, to set an integer field i to 100:
179  *
180  * JNU_SetFieldByName(env, &exc, obj, "i", "I", 100);
181  *
182  * To set a float field f to 12.3:
183  *
184  * JNU_SetFieldByName(env, &exc, obj, "f", "F", 12.3);
185  *
186  * The caller should check for exceptions by setting hasException
187  * argument. If the caller is not interested in whether an exception
188  * has occurred, pass in NULL.
189  */
190 JNIEXPORT jvalue JNICALL
191 JNU_GetFieldByName(JNIEnv *env,
192                    jboolean *hasException,
193                    jobject obj,
194                    const char *name,
195                    const char *sig);
196 JNIEXPORT void JNICALL
197 JNU_SetFieldByName(JNIEnv *env,
198                    jboolean *hasException,
199                    jobject obj,
200                    const char *name,
201                    const char *sig,
202                    ...);
203 
204 JNIEXPORT jvalue JNICALL
205 JNU_GetStaticFieldByName(JNIEnv *env,
206                          jboolean *hasException,
207                          const char *classname,
208                          const char *name,
209                          const char *sig);
210 
211 
212 /************************************************************************
213  * Miscellaneous utilities used by the class libraries
214  */
215 
216 #define IS_NULL(obj) ((obj) == NULL)
217 #define JNU_IsNull(env,obj) ((obj) == NULL)
218 
219 /************************************************************************
220  * Miscellaneous utilities used by the class libraries to return from
221  * a function if a value is NULL or an exception is pending.
222  */
223 
224 #define CHECK_NULL(x)                           \
225     do {                                        \
226         if ((x) == NULL) {                      \
227             return;                             \
228         }                                       \
229     } while (0)                                 \
230 
231 #define CHECK_NULL_THROW_NPE(env, x, msg)         \
232     do {                                        \
233         if ((x) == NULL) {                      \
234            JNU_ThrowNullPointerException((env), (msg));\
235            return;                              \
236         }                                       \
237     } while(0)                                  \
238 
239 #define CHECK_NULL_THROW_NPE_RETURN(env, x, msg, z)\
240     do {                                        \
241         if ((x) == NULL) {                      \
242            JNU_ThrowNullPointerException((env), (msg));\
243            return (z);                          \
244         }                                       \
245     } while(0)                                  \
246 
247 #define CHECK_NULL_RETURN(x, y)                 \
248     do {                                        \
249         if ((x) == NULL) {                      \
250             return (y);                         \
251         }                                       \
252     } while (0)                                 \
253 
254 #ifdef __cplusplus
255 #define JNU_CHECK_EXCEPTION(env)                \
256     do {                                        \
257         if ((env)->ExceptionCheck()) {          \
258             return;                             \
259         }                                       \
260     } while (0)                                 \
261 
262 #define JNU_CHECK_EXCEPTION_RETURN(env, y)      \
263     do {                                        \
264         if ((env)->ExceptionCheck()) {          \
265             return (y);                         \
266         }                                       \
267     } while (0)
268 #else
269 #define JNU_CHECK_EXCEPTION(env)                \
270     do {                                        \
271         if ((*env)->ExceptionCheck(env)) {      \
272             return;                             \
273         }                                       \
274     } while (0)                                 \
275 
276 #define JNU_CHECK_EXCEPTION_RETURN(env, y)      \
277     do {                                        \
278         if ((*env)->ExceptionCheck(env)) {      \
279             return (y);                         \
280         }                                       \
281     } while (0)
282 #endif /* __cplusplus */
283 
284 /************************************************************************
285  * Debugging utilities
286  */
287 
288 JNIEXPORT jstring JNICALL
289 JNU_ToString(JNIEnv *env, jobject object);
290 
291 
292 /*
293  * Package shorthand for use by native libraries
294  */
295 #define JNU_JAVAPKG         "java/lang/"
296 #define JNU_JAVAIOPKG       "java/io/"
297 #define JNU_JAVANETPKG      "java/net/"
298 
299 /*
300  * Check if the current thread is attached to the VM, and returns
301  * the JNIEnv of the specified version if the thread is attached.
302  *
303  * If the current thread is not attached, this function returns 0.
304  *
305  * If the current thread is attached, this function returns the
306  * JNI environment, or returns (void *)JNI_ERR if the specified
307  * version is not supported.
308  */
309 JNIEXPORT void * JNICALL
310 JNU_GetEnv(JavaVM *vm, jint version);
311 
312 /*
313  * Warning free access to pointers stored in Java long fields.
314  */
315 #define JNU_GetLongFieldAsPtr(env,obj,id) \
316     (jlong_to_ptr((*(env))->GetLongField((env),(obj),(id))))
317 #define JNU_SetLongFieldFromPtr(env,obj,id,val) \
318     (*(env))->SetLongField((env),(obj),(id),ptr_to_jlong(val))
319 
320 /*
321  * Internal use only.
322  */
323 enum {
324     NO_ENCODING_YET = 0,        /* "sun.jnu.encoding" not yet set */
325     NO_FAST_ENCODING,           /* Platform encoding is not fast */
326     FAST_8859_1,                /* ISO-8859-1 */
327     FAST_CP1252,                /* MS-DOS Cp1252 */
328     FAST_646_US,                /* US-ASCII : ISO646-US */
329     FAST_UTF_8
330 };
331 
332 JNIEXPORT void InitializeEncoding(JNIEnv *env, const char *name);
333 
334 void* getProcessHandle();
335 
336 void* findEntryInProcess(const char* name);
337 
338 void buildJniFunctionName(const char *sym, const char *cname,
339                           char *jniEntryName);
340 
341 JNIEXPORT size_t JNICALL
342 getLastErrorString(char *buf, size_t len);
343 
344 JNIEXPORT int JNICALL
345 getErrorString(int err, char *buf, size_t len);
346 
347 #ifdef STATIC_BUILD
348 /* Macros for handling declaration of static/dynamic
349  * JNI library Load/Unload functions
350  *
351  * Use DEF_JNI_On{Un}Load when you want a static and non-static entry points.
352  * Use DEF_STATIC_JNI_On{Un}Load when you only want a static one.
353  *
354  * LIBRARY_NAME must be set to the name of the library
355  */
356 
357 /* These three macros are needed to get proper concatenation of
358  * the LIBRARY_NAME
359  *
360  * NOTE: LIBRARY_NAME must be set for static builds.
361  */
362 #define ADD_LIB_NAME3(name, lib) name ## lib
363 #define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
364 #define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
365 
366 #define DEF_JNI_OnLoad \
367 ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) \
368 { \
369   jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)(JavaVM *vm, void *reserved); \
370   ADD_LIB_NAME(JNI_OnLoad_dynamic_)(vm, reserved); \
371   return JNI_VERSION_1_8; \
372 } \
373 jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)
374 
375 #define DEF_STATIC_JNI_OnLoad \
376 JNIEXPORT jint JNICALL ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) { \
377     return JNI_VERSION_1_8; \
378 }
379 
380 #define DEF_JNI_OnUnload \
381 ADD_LIB_NAME(JNI_OnUnload_)(JavaVM *vm, void *reserved) \
382 { \
383   void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)(JavaVM *vm, void *reserved); \
384   ADD_LIB_NAME(JNI_OnUnload_dynamic_)(vm, reserved); \
385 } \
386 void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)
387 
388 #define DEF_STATIC_JNI_OnUnload \
389 ADD_LIB_NAME(JNI_OnUnload_)
390 
391 #else
392 
393 #define DEF_JNI_OnLoad JNI_OnLoad
394 #define DEF_STATIC_JNI_OnLoad
395 #define DEF_JNI_OnUnload JNI_OnUnload
396 #define DEF_STATIC_JNI_OnUnload
397 #endif
398 
399 #ifdef STATIC_BUILD
400 /* Macros for handling declaration of static/dynamic
401  * Agent library Load/Attach/Unload functions
402  *
403  * Use DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
404  *     when you want both static and non-static entry points.
405  * Use DEF_STATIC_Agent_OnLoad, DEF_STATIC_Agent_OnAttach or
406  *     DEF_STATIC_Agent_OnUnload when you only want a static one.
407  *
408  * LIBRARY_NAME must be set to the name of the library for static builds.
409  */
410 
411 #define DEF_Agent_OnLoad \
412 ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
413 { \
414   jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
415   return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
416 } \
417 jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
418 
419 #define DEF_STATIC_Agent_OnLoad \
420 JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
421     return JNI_FALSE; \
422 }
423 
424 #define DEF_Agent_OnAttach \
425 ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
426 { \
427   jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
428   return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
429 } \
430 jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
431 
432 #define DEF_STATIC_Agent_OnAttach \
433 JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
434     return JNI_FALSE; \
435 }
436 
437 #define DEF_Agent_OnUnload \
438 ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
439 { \
440   void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
441   ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
442 } \
443 void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
444 
445 #define DEF_STATIC_Agent_OnUnload \
446 ADD_LIB_NAME(Agent_OnUnload_)
447 
448 #else
449 #define DEF_Agent_OnLoad Agent_OnLoad
450 #define DEF_Agent_OnAttach Agent_OnAttach
451 #define DEF_Agent_OnUnload Agent_OnUnload
452 #define DEF_STATIC_Agent_OnLoad
453 #define DEF_STATIC_Agent_OnAttach
454 #define DEF_STATIC_Agent_OnUnload
455 #endif
456 
457 #ifdef __cplusplus
458 } /* extern "C" */
459 #endif /* __cplusplus */
460 
461 #endif /* JNI_UTIL_H */
462