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_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 buildJniFunctionName(const char *sym, const char *cname,
 337                           char *jniEntryName);
 338 
 339 JNIEXPORT size_t JNICALL
 340 getLastErrorString(char *buf, size_t len);
 341 
 342 JNIEXPORT int JNICALL
 343 getErrorString(int err, char *buf, size_t len);
 344 
 345 #ifdef STATIC_BUILD
 346 /* Macros for handling declaration of static/dynamic
 347  * JNI library Load/Unload functions
 348  *
 349  * Use DEF_JNI_On{Un}Load when you want a static and non-static entry points.
 350  * Use DEF_STATIC_JNI_On{Un}Load when you only want a static one.
 351  *
 352  * LIBRARY_NAME must be set to the name of the library
 353  */
 354 
 355 /* These three macros are needed to get proper concatenation of
 356  * the LIBRARY_NAME
 357  *
 358  * NOTE: LIBRARY_NAME must be set for static builds.
 359  */
 360 #define ADD_LIB_NAME3(name, lib) name ## lib
 361 #define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
 362 #define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
 363 
 364 #define DEF_JNI_OnLoad \
 365 ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) \
 366 { \
 367   jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)(JavaVM *vm, void *reserved); \
 368   ADD_LIB_NAME(JNI_OnLoad_dynamic_)(vm, reserved); \
 369   return JNI_VERSION_1_8; \
 370 } \
 371 jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)
 372 
 373 #define DEF_STATIC_JNI_OnLoad \
 374 JNIEXPORT jint JNICALL ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) { \
 375     return JNI_VERSION_1_8; \
 376 }
 377 
 378 #define DEF_JNI_OnUnload \
 379 ADD_LIB_NAME(JNI_OnUnload_)(JavaVM *vm, void *reserved) \
 380 { \
 381   void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)(JavaVM *vm, void *reserved); \
 382   ADD_LIB_NAME(JNI_OnUnload_dynamic_)(vm, reserved); \
 383 } \
 384 void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)
 385 
 386 #define DEF_STATIC_JNI_OnUnload \
 387 ADD_LIB_NAME(JNI_OnUnload_)
 388 
 389 #else
 390 
 391 #define DEF_JNI_OnLoad JNI_OnLoad
 392 #define DEF_STATIC_JNI_OnLoad
 393 #define DEF_JNI_OnUnload JNI_OnUnload
 394 #define DEF_STATIC_JNI_OnUnload
 395 #endif
 396 
 397 #ifdef STATIC_BUILD
 398 /* Macros for handling declaration of static/dynamic
 399  * Agent library Load/Attach/Unload functions
 400  *
 401  * Use DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
 402  *     when you want both static and non-static entry points.
 403  * Use DEF_STATIC_Agent_OnLoad, DEF_STATIC_Agent_OnAttach or
 404  *     DEF_STATIC_Agent_OnUnload when you only want a static one.
 405  *
 406  * LIBRARY_NAME must be set to the name of the library for static builds.
 407  */
 408 
 409 #define DEF_Agent_OnLoad \
 410 ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
 411 { \
 412   jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
 413   return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
 414 } \
 415 jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
 416 
 417 #define DEF_STATIC_Agent_OnLoad \
 418 JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
 419     return JNI_FALSE; \
 420 }
 421 
 422 #define DEF_Agent_OnAttach \
 423 ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
 424 { \
 425   jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
 426   return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
 427 } \
 428 jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
 429 
 430 #define DEF_STATIC_Agent_OnAttach \
 431 JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
 432     return JNI_FALSE; \
 433 }
 434 
 435 #define DEF_Agent_OnUnload \
 436 ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
 437 { \
 438   void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
 439   ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
 440 } \
 441 void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
 442 
 443 #define DEF_STATIC_Agent_OnUnload \
 444 ADD_LIB_NAME(Agent_OnUnload_)
 445 
 446 #else
 447 #define DEF_Agent_OnLoad Agent_OnLoad
 448 #define DEF_Agent_OnAttach Agent_OnAttach
 449 #define DEF_Agent_OnUnload Agent_OnUnload
 450 #define DEF_STATIC_Agent_OnLoad
 451 #define DEF_STATIC_Agent_OnAttach
 452 #define DEF_STATIC_Agent_OnUnload
 453 #endif
 454 
 455 #ifdef __cplusplus
 456 } /* extern "C" */
 457 #endif /* __cplusplus */
 458 
 459 #endif /* JNI_UTIL_H */