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