1 /*
2 * Copyright (C) 2010 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 #define LOG_TAG "JniConstants"
18
19 #include "JniConstants.h"
20
21 #include <atomic>
22 #include <mutex>
23 #include <stdlib.h>
24
25 #include <log/log.h>
26 #include <nativehelper/ScopedLocalRef.h>
27
28 namespace {
29
findClass(JNIEnv * env,const char * name)30 jclass findClass(JNIEnv* env, const char* name) {
31 ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
32 jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
33 if (result == NULL) {
34 ALOGE("failed to find class '%s'", name);
35 abort();
36 }
37 return result;
38 }
39
40 // Mutex protecting static variables
41 static std::mutex g_constants_mutex;
42
43 // Flag indicating whether cached constants are valid
44 static bool g_constants_valid = false;
45
46 // Constants
47 jclass booleanClass;
48 jclass byteBufferClass;
49 jclass doubleClass;
50 jclass errnoExceptionClass;
51 jclass fileDescriptorClass;
52 jclass gaiExceptionClass;
53 jclass inet6AddressClass;
54 jclass inet6AddressHolderClass;
55 jclass inetAddressClass;
56 jclass inetAddressHolderClass;
57 jclass inetSocketAddressClass;
58 jclass inetSocketAddressHolderClass;
59 jclass integerClass;
60 jclass localeDataClass;
61 jclass longClass;
62 jclass netlinkSocketAddressClass;
63 jclass packetSocketAddressClass;
64 jclass vmSocketAddressClass;
65 jclass primitiveByteArrayClass;
66 jclass stringClass;
67 jclass structAddrinfoClass;
68 jclass structCmsghdrClass;
69 jclass structGroupReqClass;
70 jclass structIfaddrsClass;
71 jclass structLingerClass;
72 jclass structMsghdrClass;
73 jclass structPasswdClass;
74 jclass structPollfdClass;
75 jclass structStatClass;
76 jclass structStatVfsClass;
77 jclass structTimespecClass;
78 jclass structTimevalClass;
79 jclass structUcredClass;
80 jclass structUtsnameClass;
81 jclass unixSocketAddressClass;
82
83 // EnsureJniConstantsInitialized initializes cached constants. It should be
84 // called before returning a heap object from the cache to ensure cache is
85 // initialized. This pattern is only necessary because if a process finishes one
86 // runtime and starts another then JNI_OnLoad may not be called.
EnsureJniConstantsInitialized(JNIEnv * env)87 void EnsureJniConstantsInitialized(JNIEnv* env) {
88 if (g_constants_valid) {
89 return;
90 }
91
92 std::lock_guard guard(g_constants_mutex);
93 if (g_constants_valid) {
94 return;
95 }
96
97 booleanClass = findClass(env, "java/lang/Boolean");
98 byteBufferClass = findClass(env, "java/nio/ByteBuffer");
99 doubleClass = findClass(env, "java/lang/Double");
100 errnoExceptionClass = findClass(env, "android/system/ErrnoException");
101 fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
102 gaiExceptionClass = findClass(env, "android/system/GaiException");
103 inet6AddressClass = findClass(env, "java/net/Inet6Address");
104 inet6AddressHolderClass = findClass(env, "java/net/Inet6Address$Inet6AddressHolder");
105 inetAddressClass = findClass(env, "java/net/InetAddress");
106 inetAddressHolderClass = findClass(env, "java/net/InetAddress$InetAddressHolder");
107 inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
108 inetSocketAddressHolderClass = findClass(env, "java/net/InetSocketAddress$InetSocketAddressHolder");
109 integerClass = findClass(env, "java/lang/Integer");
110 localeDataClass = findClass(env, "libcore/icu/LocaleData");
111 longClass = findClass(env, "java/lang/Long");
112 netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress");
113 packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress");
114 vmSocketAddressClass = findClass(env, "android/system/VmSocketAddress");
115 primitiveByteArrayClass = findClass(env, "[B");
116 stringClass = findClass(env, "java/lang/String");
117 structAddrinfoClass = findClass(env, "android/system/StructAddrinfo");
118 structCmsghdrClass = findClass(env, "android/system/StructCmsghdr");
119 structGroupReqClass = findClass(env, "android/system/StructGroupReq");
120 structIfaddrsClass = findClass(env, "android/system/StructIfaddrs");
121 structLingerClass = findClass(env, "android/system/StructLinger");
122 structMsghdrClass = findClass(env, "android/system/StructMsghdr");
123 structPasswdClass = findClass(env, "android/system/StructPasswd");
124 structPollfdClass = findClass(env, "android/system/StructPollfd");
125 structStatClass = findClass(env, "android/system/StructStat");
126 structStatVfsClass = findClass(env, "android/system/StructStatVfs");
127 structTimevalClass = findClass(env, "android/system/StructTimeval");
128 structTimespecClass = findClass(env, "android/system/StructTimespec");
129 structUcredClass = findClass(env, "android/system/StructUcred");
130 structUtsnameClass = findClass(env, "android/system/StructUtsname");
131 unixSocketAddressClass = findClass(env, "android/system/UnixSocketAddress");
132
133 g_constants_valid = true;
134 }
135
136 } // namespace
137
Initialize(JNIEnv * env)138 void JniConstants::Initialize(JNIEnv* env) {
139 EnsureJniConstantsInitialized(env);
140 }
141
Invalidate()142 void JniConstants::Invalidate() {
143 // This method is called when a new runtime instance is created. There is no
144 // notification of a runtime instance being destroyed in the JNI interface
145 // so we piggyback on creation. Since only one runtime is supported at a
146 // time, we know the constants are invalid when JNI_CreateJavaVM() is
147 // called.
148 //
149 // Clean shutdown would require calling DeleteGlobalRef() for each of the
150 // class references, but JavaVM is unavailable because ART only calls this
151 // once all threads are unregistered.
152 std::lock_guard guard(g_constants_mutex);
153 g_constants_valid = false;
154 }
155
GetBooleanClass(JNIEnv * env)156 jclass JniConstants::GetBooleanClass(JNIEnv* env) {
157 EnsureJniConstantsInitialized(env);
158 return booleanClass;
159 }
160
GetByteBufferClass(JNIEnv * env)161 jclass JniConstants::GetByteBufferClass(JNIEnv* env) {
162 EnsureJniConstantsInitialized(env);
163 return byteBufferClass;
164 }
165
GetDoubleClass(JNIEnv * env)166 jclass JniConstants::GetDoubleClass(JNIEnv* env) {
167 EnsureJniConstantsInitialized(env);
168 return doubleClass;
169 }
170
GetErrnoExceptionClass(JNIEnv * env)171 jclass JniConstants::GetErrnoExceptionClass(JNIEnv* env) {
172 EnsureJniConstantsInitialized(env);
173 return errnoExceptionClass;
174 }
175
GetFileDescriptorClass(JNIEnv * env)176 jclass JniConstants::GetFileDescriptorClass(JNIEnv* env) {
177 EnsureJniConstantsInitialized(env);
178 return fileDescriptorClass;
179 }
180
GetGaiExceptionClass(JNIEnv * env)181 jclass JniConstants::GetGaiExceptionClass(JNIEnv* env) {
182 EnsureJniConstantsInitialized(env);
183 return gaiExceptionClass;
184 }
185
GetInet6AddressClass(JNIEnv * env)186 jclass JniConstants::GetInet6AddressClass(JNIEnv* env) {
187 EnsureJniConstantsInitialized(env);
188 return inet6AddressClass;
189 }
190
GetInet6AddressHolderClass(JNIEnv * env)191 jclass JniConstants::GetInet6AddressHolderClass(JNIEnv* env) {
192 EnsureJniConstantsInitialized(env);
193 return inet6AddressHolderClass;
194 }
195
GetInetAddressClass(JNIEnv * env)196 jclass JniConstants::GetInetAddressClass(JNIEnv* env) {
197 EnsureJniConstantsInitialized(env);
198 return inetAddressClass;
199 }
200
GetInetAddressHolderClass(JNIEnv * env)201 jclass JniConstants::GetInetAddressHolderClass(JNIEnv* env) {
202 EnsureJniConstantsInitialized(env);
203 return inetAddressHolderClass;
204 }
205
GetInetSocketAddressClass(JNIEnv * env)206 jclass JniConstants::GetInetSocketAddressClass(JNIEnv* env) {
207 EnsureJniConstantsInitialized(env);
208 return inetSocketAddressClass;
209 }
210
GetInetSocketAddressHolderClass(JNIEnv * env)211 jclass JniConstants::GetInetSocketAddressHolderClass(JNIEnv* env) {
212 EnsureJniConstantsInitialized(env);
213 return inetSocketAddressHolderClass;
214 }
215
GetIntegerClass(JNIEnv * env)216 jclass JniConstants::GetIntegerClass(JNIEnv* env) {
217 EnsureJniConstantsInitialized(env);
218 return integerClass;
219 }
220
GetLocaleDataClass(JNIEnv * env)221 jclass JniConstants::GetLocaleDataClass(JNIEnv* env) {
222 EnsureJniConstantsInitialized(env);
223 return localeDataClass;
224 }
225
GetLongClass(JNIEnv * env)226 jclass JniConstants::GetLongClass(JNIEnv* env) {
227 EnsureJniConstantsInitialized(env);
228 return longClass;
229 }
230
GetNetlinkSocketAddressClass(JNIEnv * env)231 jclass JniConstants::GetNetlinkSocketAddressClass(JNIEnv* env) {
232 EnsureJniConstantsInitialized(env);
233 return netlinkSocketAddressClass;
234 }
235
GetPacketSocketAddressClass(JNIEnv * env)236 jclass JniConstants::GetPacketSocketAddressClass(JNIEnv* env) {
237 EnsureJniConstantsInitialized(env);
238 return packetSocketAddressClass;
239 }
240
GetVmSocketAddressClass(JNIEnv * env)241 jclass JniConstants::GetVmSocketAddressClass(JNIEnv* env) {
242 EnsureJniConstantsInitialized(env);
243 return vmSocketAddressClass;
244 }
245
GetPrimitiveByteArrayClass(JNIEnv * env)246 jclass JniConstants::GetPrimitiveByteArrayClass(JNIEnv* env) {
247 EnsureJniConstantsInitialized(env);
248 return primitiveByteArrayClass;
249 }
250
GetStringClass(JNIEnv * env)251 jclass JniConstants::GetStringClass(JNIEnv* env) {
252 EnsureJniConstantsInitialized(env);
253 return stringClass;
254 }
255
GetStructAddrinfoClass(JNIEnv * env)256 jclass JniConstants::GetStructAddrinfoClass(JNIEnv* env) {
257 EnsureJniConstantsInitialized(env);
258 return structAddrinfoClass;
259 }
260
GetStructCmsghdrClass(JNIEnv * env)261 jclass JniConstants::GetStructCmsghdrClass(JNIEnv* env) {
262 EnsureJniConstantsInitialized(env);
263 return structCmsghdrClass;
264 }
265
GetStructGroupReqClass(JNIEnv * env)266 jclass JniConstants::GetStructGroupReqClass(JNIEnv* env) {
267 EnsureJniConstantsInitialized(env);
268 return structGroupReqClass;
269 }
270
GetStructIfaddrsClass(JNIEnv * env)271 jclass JniConstants::GetStructIfaddrsClass(JNIEnv* env) {
272 EnsureJniConstantsInitialized(env);
273 return structIfaddrsClass;
274 }
275
GetStructLingerClass(JNIEnv * env)276 jclass JniConstants::GetStructLingerClass(JNIEnv* env) {
277 EnsureJniConstantsInitialized(env);
278 return structLingerClass;
279 }
280
GetStructMsghdrClass(JNIEnv * env)281 jclass JniConstants::GetStructMsghdrClass(JNIEnv* env) {
282 EnsureJniConstantsInitialized(env);
283 return structMsghdrClass;
284 }
285
GetStructPasswdClass(JNIEnv * env)286 jclass JniConstants::GetStructPasswdClass(JNIEnv* env) {
287 EnsureJniConstantsInitialized(env);
288 return structPasswdClass;
289 }
290
GetStructPollfdClass(JNIEnv * env)291 jclass JniConstants::GetStructPollfdClass(JNIEnv* env) {
292 EnsureJniConstantsInitialized(env);
293 return structPollfdClass;
294 }
295
GetStructStatClass(JNIEnv * env)296 jclass JniConstants::GetStructStatClass(JNIEnv* env) {
297 EnsureJniConstantsInitialized(env);
298 return structStatClass;
299 }
300
GetStructStatVfsClass(JNIEnv * env)301 jclass JniConstants::GetStructStatVfsClass(JNIEnv* env) {
302 EnsureJniConstantsInitialized(env);
303 return structStatVfsClass;
304 }
305
GetStructTimespecClass(JNIEnv * env)306 jclass JniConstants::GetStructTimespecClass(JNIEnv* env) {
307 EnsureJniConstantsInitialized(env);
308 return structTimespecClass;
309 }
310
GetStructTimevalClass(JNIEnv * env)311 jclass JniConstants::GetStructTimevalClass(JNIEnv* env) {
312 EnsureJniConstantsInitialized(env);
313 return structTimevalClass;
314 }
315
GetStructUcredClass(JNIEnv * env)316 jclass JniConstants::GetStructUcredClass(JNIEnv* env) {
317 EnsureJniConstantsInitialized(env);
318 return structUcredClass;
319 }
320
GetStructUtsnameClass(JNIEnv * env)321 jclass JniConstants::GetStructUtsnameClass(JNIEnv* env) {
322 EnsureJniConstantsInitialized(env);
323 return structUtsnameClass;
324 }
325
GetUnixSocketAddressClass(JNIEnv * env)326 jclass JniConstants::GetUnixSocketAddressClass(JNIEnv* env) {
327 EnsureJniConstantsInitialized(env);
328 return unixSocketAddressClass;
329 }
330