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