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 charsetICUClass;
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 patternSyntaxExceptionClass;
65 jclass stringClass;
66 jclass structAddrinfoClass;
67 jclass structFlockClass;
68 jclass structGroupReqClass;
69 jclass structIfaddrsClass;
70 jclass structLingerClass;
71 jclass structPasswdClass;
72 jclass structPollfdClass;
73 jclass structStatClass;
74 jclass structStatVfsClass;
75 jclass structTimespecClass;
76 jclass structTimevalClass;
77 jclass structUcredClass;
78 jclass structUtsnameClass;
79 jclass unixSocketAddressClass;
80
81 // EnsureJniConstantsInitialized initializes cached constants. It should be
82 // called before returning a heap object from the cache to ensure cache is
83 // initialized. This pattern is only necessary because if a process finishes one
84 // runtime and starts another then JNI_OnLoad may not be called.
EnsureJniConstantsInitialized(JNIEnv * env)85 void EnsureJniConstantsInitialized(JNIEnv* env) {
86 if (g_constants_valid) {
87 return;
88 }
89
90 std::lock_guard guard(g_constants_mutex);
91 if (g_constants_valid) {
92 return;
93 }
94
95 booleanClass = findClass(env, "java/lang/Boolean");
96 charsetICUClass = findClass(env, "java/nio/charset/CharsetICU");
97 doubleClass = findClass(env, "java/lang/Double");
98 errnoExceptionClass = findClass(env, "android/system/ErrnoException");
99 fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
100 gaiExceptionClass = findClass(env, "android/system/GaiException");
101 inet6AddressClass = findClass(env, "java/net/Inet6Address");
102 inet6AddressHolderClass = findClass(env, "java/net/Inet6Address$Inet6AddressHolder");
103 inetAddressClass = findClass(env, "java/net/InetAddress");
104 inetAddressHolderClass = findClass(env, "java/net/InetAddress$InetAddressHolder");
105 inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
106 inetSocketAddressHolderClass = findClass(env, "java/net/InetSocketAddress$InetSocketAddressHolder");
107 integerClass = findClass(env, "java/lang/Integer");
108 localeDataClass = findClass(env, "libcore/icu/LocaleData");
109 longClass = findClass(env, "java/lang/Long");
110 netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress");
111 packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress");
112 patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException");
113 stringClass = findClass(env, "java/lang/String");
114 structAddrinfoClass = findClass(env, "android/system/StructAddrinfo");
115 structFlockClass = findClass(env, "android/system/StructFlock");
116 structGroupReqClass = findClass(env, "android/system/StructGroupReq");
117 structIfaddrsClass = findClass(env, "android/system/StructIfaddrs");
118 structLingerClass = findClass(env, "android/system/StructLinger");
119 structPasswdClass = findClass(env, "android/system/StructPasswd");
120 structPollfdClass = findClass(env, "android/system/StructPollfd");
121 structStatClass = findClass(env, "android/system/StructStat");
122 structStatVfsClass = findClass(env, "android/system/StructStatVfs");
123 structTimevalClass = findClass(env, "android/system/StructTimeval");
124 structTimespecClass = findClass(env, "android/system/StructTimespec");
125 structUcredClass = findClass(env, "android/system/StructUcred");
126 structUtsnameClass = findClass(env, "android/system/StructUtsname");
127 unixSocketAddressClass = findClass(env, "android/system/UnixSocketAddress");
128
129 g_constants_valid = true;
130 }
131
132 } // namespace
133
Initialize(JNIEnv * env)134 void JniConstants::Initialize(JNIEnv* env) {
135 EnsureJniConstantsInitialized(env);
136 }
137
Invalidate()138 void JniConstants::Invalidate() {
139 std::lock_guard guard(g_constants_mutex);
140 g_constants_valid = false;
141 }
142
GetBooleanClass(JNIEnv * env)143 jclass JniConstants::GetBooleanClass(JNIEnv* env) {
144 EnsureJniConstantsInitialized(env);
145 return booleanClass;
146 }
147
GetCharsetICUClass(JNIEnv * env)148 jclass JniConstants::GetCharsetICUClass(JNIEnv* env) {
149 EnsureJniConstantsInitialized(env);
150 return charsetICUClass;
151 }
152
GetDoubleClass(JNIEnv * env)153 jclass JniConstants::GetDoubleClass(JNIEnv* env) {
154 EnsureJniConstantsInitialized(env);
155 return doubleClass;
156 }
157
GetErrnoExceptionClass(JNIEnv * env)158 jclass JniConstants::GetErrnoExceptionClass(JNIEnv* env) {
159 EnsureJniConstantsInitialized(env);
160 return errnoExceptionClass;
161 }
162
GetFileDescriptorClass(JNIEnv * env)163 jclass JniConstants::GetFileDescriptorClass(JNIEnv* env) {
164 EnsureJniConstantsInitialized(env);
165 return fileDescriptorClass;
166 }
167
GetGaiExceptionClass(JNIEnv * env)168 jclass JniConstants::GetGaiExceptionClass(JNIEnv* env) {
169 EnsureJniConstantsInitialized(env);
170 return gaiExceptionClass;
171 }
172
GetInet6AddressClass(JNIEnv * env)173 jclass JniConstants::GetInet6AddressClass(JNIEnv* env) {
174 EnsureJniConstantsInitialized(env);
175 return inet6AddressClass;
176 }
177
GetInet6AddressHolderClass(JNIEnv * env)178 jclass JniConstants::GetInet6AddressHolderClass(JNIEnv* env) {
179 EnsureJniConstantsInitialized(env);
180 return inet6AddressHolderClass;
181 }
182
GetInetAddressClass(JNIEnv * env)183 jclass JniConstants::GetInetAddressClass(JNIEnv* env) {
184 EnsureJniConstantsInitialized(env);
185 return inetAddressClass;
186 }
187
GetInetAddressHolderClass(JNIEnv * env)188 jclass JniConstants::GetInetAddressHolderClass(JNIEnv* env) {
189 EnsureJniConstantsInitialized(env);
190 return inetAddressHolderClass;
191 }
192
GetInetSocketAddressClass(JNIEnv * env)193 jclass JniConstants::GetInetSocketAddressClass(JNIEnv* env) {
194 EnsureJniConstantsInitialized(env);
195 return inetSocketAddressClass;
196 }
197
GetInetSocketAddressHolderClass(JNIEnv * env)198 jclass JniConstants::GetInetSocketAddressHolderClass(JNIEnv* env) {
199 EnsureJniConstantsInitialized(env);
200 return inetSocketAddressHolderClass;
201 }
202
GetIntegerClass(JNIEnv * env)203 jclass JniConstants::GetIntegerClass(JNIEnv* env) {
204 EnsureJniConstantsInitialized(env);
205 return integerClass;
206 }
207
GetLocaleDataClass(JNIEnv * env)208 jclass JniConstants::GetLocaleDataClass(JNIEnv* env) {
209 EnsureJniConstantsInitialized(env);
210 return localeDataClass;
211 }
212
GetLongClass(JNIEnv * env)213 jclass JniConstants::GetLongClass(JNIEnv* env) {
214 EnsureJniConstantsInitialized(env);
215 return longClass;
216 }
217
GetNetlinkSocketAddressClass(JNIEnv * env)218 jclass JniConstants::GetNetlinkSocketAddressClass(JNIEnv* env) {
219 EnsureJniConstantsInitialized(env);
220 return netlinkSocketAddressClass;
221 }
222
GetPacketSocketAddressClass(JNIEnv * env)223 jclass JniConstants::GetPacketSocketAddressClass(JNIEnv* env) {
224 EnsureJniConstantsInitialized(env);
225 return packetSocketAddressClass;
226 }
227
GetPatternSyntaxExceptionClass(JNIEnv * env)228 jclass JniConstants::GetPatternSyntaxExceptionClass(JNIEnv* env) {
229 EnsureJniConstantsInitialized(env);
230 return patternSyntaxExceptionClass;
231 }
232
GetStringClass(JNIEnv * env)233 jclass JniConstants::GetStringClass(JNIEnv* env) {
234 EnsureJniConstantsInitialized(env);
235 return stringClass;
236 }
237
GetStructAddrinfoClass(JNIEnv * env)238 jclass JniConstants::GetStructAddrinfoClass(JNIEnv* env) {
239 EnsureJniConstantsInitialized(env);
240 return structAddrinfoClass;
241 }
242
GetStructFlockClass(JNIEnv * env)243 jclass JniConstants::GetStructFlockClass(JNIEnv* env) {
244 EnsureJniConstantsInitialized(env);
245 return structFlockClass;
246 }
247
GetStructGroupReqClass(JNIEnv * env)248 jclass JniConstants::GetStructGroupReqClass(JNIEnv* env) {
249 EnsureJniConstantsInitialized(env);
250 return structGroupReqClass;
251 }
252
GetStructIfaddrsClass(JNIEnv * env)253 jclass JniConstants::GetStructIfaddrsClass(JNIEnv* env) {
254 EnsureJniConstantsInitialized(env);
255 return structIfaddrsClass;
256 }
257
GetStructLingerClass(JNIEnv * env)258 jclass JniConstants::GetStructLingerClass(JNIEnv* env) {
259 EnsureJniConstantsInitialized(env);
260 return structLingerClass;
261 }
262
GetStructPasswdClass(JNIEnv * env)263 jclass JniConstants::GetStructPasswdClass(JNIEnv* env) {
264 EnsureJniConstantsInitialized(env);
265 return structPasswdClass;
266 }
267
GetStructPollfdClass(JNIEnv * env)268 jclass JniConstants::GetStructPollfdClass(JNIEnv* env) {
269 EnsureJniConstantsInitialized(env);
270 return structPollfdClass;
271 }
272
GetStructStatClass(JNIEnv * env)273 jclass JniConstants::GetStructStatClass(JNIEnv* env) {
274 EnsureJniConstantsInitialized(env);
275 return structStatClass;
276 }
277
GetStructStatVfsClass(JNIEnv * env)278 jclass JniConstants::GetStructStatVfsClass(JNIEnv* env) {
279 EnsureJniConstantsInitialized(env);
280 return structStatVfsClass;
281 }
282
GetStructTimespecClass(JNIEnv * env)283 jclass JniConstants::GetStructTimespecClass(JNIEnv* env) {
284 EnsureJniConstantsInitialized(env);
285 return structTimespecClass;
286 }
287
GetStructTimevalClass(JNIEnv * env)288 jclass JniConstants::GetStructTimevalClass(JNIEnv* env) {
289 EnsureJniConstantsInitialized(env);
290 return structTimevalClass;
291 }
292
GetStructUcredClass(JNIEnv * env)293 jclass JniConstants::GetStructUcredClass(JNIEnv* env) {
294 EnsureJniConstantsInitialized(env);
295 return structUcredClass;
296 }
297
GetStructUtsnameClass(JNIEnv * env)298 jclass JniConstants::GetStructUtsnameClass(JNIEnv* env) {
299 EnsureJniConstantsInitialized(env);
300 return structUtsnameClass;
301 }
302
GetUnixSocketAddressClass(JNIEnv * env)303 jclass JniConstants::GetUnixSocketAddressClass(JNIEnv* env) {
304 EnsureJniConstantsInitialized(env);
305 return unixSocketAddressClass;
306 }
307