1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * JNI helper functions.
19  *
20  * This file may be included by C or C++ code, which is trouble because jni.h
21  * uses different typedefs for JNIEnv in each language.
22  */
23 #pragma once
24 
25 #include <sys/cdefs.h>
26 
27 #include <errno.h>
28 #include <unistd.h>
29 
30 #include <jni.h>
31 
32 #ifndef NELEM
33 #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
34 #endif
35 
36 __BEGIN_DECLS
37 
38 
39 /*
40  * Register one or more native methods with a particular class.  "className" looks like
41  * "java/lang/String". Aborts on failure, returns 0 on success.
42  */
43 int jniRegisterNativeMethods(C_JNIEnv* env,
44                              const char* className,
45                              const JNINativeMethod* gMethods,
46                              int numMethods);
47 
48 /*
49  * Throw an exception with the specified class and an optional message.
50  *
51  * The "className" argument will be passed directly to FindClass, which
52  * takes strings with slashes (e.g. "java/lang/Object").
53  *
54  * If an exception is currently pending, we log a warning message and
55  * clear it.
56  *
57  * Returns 0 on success, nonzero if something failed (e.g. the exception
58  * class couldn't be found, so *an* exception will still be pending).
59  *
60  * Currently aborts the VM if it can't throw the exception.
61  */
62 int jniThrowException(C_JNIEnv* env, const char* className, const char* msg);
63 
64 /*
65  * Throw an exception with the specified class and formatted error message.
66  *
67  * The "className" argument will be passed directly to FindClass, which
68  * takes strings with slashes (e.g. "java/lang/Object").
69  *
70  * If an exception is currently pending, we log a warning message and
71  * clear it.
72  *
73  * Returns 0 on success, nonzero if something failed (e.g. the exception
74  * class couldn't be found, so *an* exception will still be pending).
75  *
76  * Currently aborts the VM if it can't throw the exception.
77  */
78 int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args);
79 
80 /*
81  * Throw a java.lang.NullPointerException, with an optional message.
82  */
83 int jniThrowNullPointerException(C_JNIEnv* env, const char* msg);
84 
85 /*
86  * Throw a java.lang.RuntimeException, with an optional message.
87  */
88 int jniThrowRuntimeException(C_JNIEnv* env, const char* msg);
89 
90 /*
91  * Throw a java.io.IOException, generating the message from errno.
92  */
93 int jniThrowIOException(C_JNIEnv* env, int errnum);
94 
95 /*
96  * Returns the reference from a java.lang.ref.Reference.
97  */
98 jobject jniGetReferent(C_JNIEnv* env, jobject ref);
99 
100 /*
101  * Returns a Java String object created from UTF-16 data either from jchar or,
102  * if called from C++11, char16_t (a bitwise identical distinct type).
103  */
104 jstring jniCreateString(C_JNIEnv* env, const jchar* unicodeChars, jsize len);
105 
106 /*
107  * Allocates a new array for java/lang/String instances with space for |count| elements. Elements
108  * are initially null.
109  *
110  * Returns a new array on success or nullptr in case of failure. This method raises an
111  * OutOfMemoryError exception if allocation fails.
112  */
113 jobjectArray jniCreateStringArray(C_JNIEnv* env, size_t count);
114 
115 /*
116  * Log a message and an exception.
117  * If exception is NULL, logs the current exception in the JNI environment.
118  */
119 void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception);
120 
121 __END_DECLS
122 
123 /*
124  * For C++ code, we provide inlines that map to the C functions.  g++ always
125  * inlines these, even on non-optimized builds.
126  */
127 #if defined(__cplusplus)
128 
jniRegisterNativeMethods(JNIEnv * env,const char * className,const JNINativeMethod * gMethods,int numMethods)129 inline int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) {
130     return jniRegisterNativeMethods(&env->functions, className, gMethods, numMethods);
131 }
132 
jniThrowException(JNIEnv * env,const char * className,const char * msg)133 inline int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
134     return jniThrowException(&env->functions, className, msg);
135 }
136 
137 /*
138  * Equivalent to jniThrowException but with a printf-like format string and
139  * variable-length argument list. This is only available in C++.
140  */
jniThrowExceptionFmt(JNIEnv * env,const char * className,const char * fmt,...)141 inline int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt, ...) {
142     va_list args;
143     va_start(args, fmt);
144     return jniThrowExceptionFmt(&env->functions, className, fmt, args);
145     va_end(args);
146 }
147 
jniThrowNullPointerException(JNIEnv * env,const char * msg)148 inline int jniThrowNullPointerException(JNIEnv* env, const char* msg) {
149     return jniThrowNullPointerException(&env->functions, msg);
150 }
151 
jniThrowRuntimeException(JNIEnv * env,const char * msg)152 inline int jniThrowRuntimeException(JNIEnv* env, const char* msg) {
153     return jniThrowRuntimeException(&env->functions, msg);
154 }
155 
jniThrowIOException(JNIEnv * env,int errnum)156 inline int jniThrowIOException(JNIEnv* env, int errnum) {
157     return jniThrowIOException(&env->functions, errnum);
158 }
159 
jniGetReferent(JNIEnv * env,jobject ref)160 inline jobject jniGetReferent(JNIEnv* env, jobject ref) {
161     return jniGetReferent(&env->functions, ref);
162 }
163 
jniCreateString(JNIEnv * env,const jchar * unicodeChars,jsize len)164 inline jstring jniCreateString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
165     return jniCreateString(&env->functions, unicodeChars, len);
166 }
167 
jniCreateString(JNIEnv * env,const char16_t * unicodeChars,jsize len)168 inline jstring jniCreateString(JNIEnv* env, const char16_t* unicodeChars, jsize len) {
169     return jniCreateString(&env->functions, reinterpret_cast<const jchar*>(unicodeChars), len);
170 }
171 
172 inline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) {
173     jniLogException(&env->functions, priority, tag, exception);
174 }
175 
176 #endif  // defined(__cplusplus)
177 
178