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