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