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 * TODO: remove C support.
24 */
25 #ifndef NATIVEHELPER_JNIHELP_H_
26 #define NATIVEHELPER_JNIHELP_H_
27
28 #include "jni.h"
29 #include <unistd.h>
30
31 #ifndef NELEM
32 # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
33 #endif
34
35 // TODO: the build system doesn't ensure the standard C++ library header files are on the include
36 // path when compiling C++, and this file is included all over the place.
37 #ifdef LIBCORE_CPP_JNI_HELPERS
38 #include <string>
39 #endif // LIBCORE_CPP_JNI_HELPERS
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 /*
46 * Register one or more native methods with a particular class.
47 * "className" looks like "java/lang/String". Aborts on failure.
48 * TODO: fix all callers and change the return type to void.
49 */
50 int jniRegisterNativeMethods(C_JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods);
51
52 /*
53 * Throw an exception with the specified class and an optional message.
54 *
55 * The "className" argument will be passed directly to FindClass, which
56 * takes strings with slashes (e.g. "java/lang/Object").
57 *
58 * If an exception is currently pending, we log a warning message and
59 * clear it.
60 *
61 * Returns 0 on success, nonzero if something failed (e.g. the exception
62 * class couldn't be found, so *an* exception will still be pending).
63 *
64 * Currently aborts the VM if it can't throw the exception.
65 */
66 int jniThrowException(C_JNIEnv* env, const char* className, const char* msg);
67
68 /*
69 * Throw a java.lang.NullPointerException, with an optional message.
70 */
71 int jniThrowNullPointerException(C_JNIEnv* env, const char* msg);
72
73 /*
74 * Throw a java.lang.RuntimeException, with an optional message.
75 */
76 int jniThrowRuntimeException(C_JNIEnv* env, const char* msg);
77
78 /*
79 * Throw a java.io.IOException, generating the message from errno.
80 */
81 int jniThrowIOException(C_JNIEnv* env, int errnum);
82
83 /*
84 * Return a pointer to a locale-dependent error string explaining errno
85 * value 'errnum'. The returned pointer may or may not be equal to 'buf'.
86 * This function is thread-safe (unlike strerror) and portable (unlike
87 * strerror_r).
88 */
89 const char* jniStrError(int errnum, char* buf, size_t buflen);
90
91 /*
92 * Returns a new java.io.FileDescriptor for the given int fd.
93 */
94 jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd);
95
96 /*
97 * Returns the int fd from a java.io.FileDescriptor.
98 */
99 int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor);
100
101 /*
102 * Sets the int fd in a java.io.FileDescriptor.
103 */
104 void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value);
105
106 /*
107 * Returns the reference from a java.lang.ref.Reference.
108 */
109 jobject jniGetReferent(C_JNIEnv* env, jobject ref);
110
111 /*
112 * Log a message and an exception.
113 * If exception is NULL, logs the current exception in the JNI environment.
114 */
115 void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception);
116
117 #ifdef __cplusplus
118 }
119 #endif
120
121
122 /*
123 * For C++ code, we provide inlines that map to the C functions. g++ always
124 * inlines these, even on non-optimized builds.
125 */
126 #if defined(__cplusplus)
jniRegisterNativeMethods(JNIEnv * env,const char * className,const JNINativeMethod * gMethods,int numMethods)127 inline int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) {
128 return jniRegisterNativeMethods(&env->functions, className, gMethods, numMethods);
129 }
130
jniThrowException(JNIEnv * env,const char * className,const char * msg)131 inline int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
132 return jniThrowException(&env->functions, className, msg);
133 }
134
135 extern "C" int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args);
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
jniCreateFileDescriptor(JNIEnv * env,int fd)160 inline jobject jniCreateFileDescriptor(JNIEnv* env, int fd) {
161 return jniCreateFileDescriptor(&env->functions, fd);
162 }
163
jniGetFDFromFileDescriptor(JNIEnv * env,jobject fileDescriptor)164 inline int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
165 return jniGetFDFromFileDescriptor(&env->functions, fileDescriptor);
166 }
167
jniSetFileDescriptorOfFD(JNIEnv * env,jobject fileDescriptor,int value)168 inline void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
169 jniSetFileDescriptorOfFD(&env->functions, fileDescriptor, value);
170 }
171
jniGetReferent(JNIEnv * env,jobject ref)172 inline jobject jniGetReferent(JNIEnv* env, jobject ref) {
173 return jniGetReferent(&env->functions, ref);
174 }
175
176 inline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) {
177 jniLogException(&env->functions, priority, tag, exception);
178 }
179
180 #ifdef LIBCORE_CPP_JNI_HELPERS
181
182 extern "C" std::string jniGetStackTrace(C_JNIEnv* env, jthrowable exception);
183
184 inline std::string jniGetStackTrace(JNIEnv* env, jthrowable exception = NULL) {
185 return jniGetStackTrace(&env->functions, exception);
186 }
187
188 #endif // LIBCORE_CPP_JNI_HELPERS
189
190 #endif
191
192 /*
193 * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
194 * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
195 * not already defined, then define it here.
196 */
197 #ifndef TEMP_FAILURE_RETRY
198 /* Used to retry syscalls that can return EINTR. */
199 #define TEMP_FAILURE_RETRY(exp) ({ \
200 typeof (exp) _rc; \
201 do { \
202 _rc = (exp); \
203 } while (_rc == -1 && errno == EINTR); \
204 _rc; })
205 #endif
206
207 #endif /* NATIVEHELPER_JNIHELP_H_ */
208