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