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 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. 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 138 void JniConstants::Initialize(JNIEnv* env) { 139 EnsureJniConstantsInitialized(env); 140 } 141 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 156 jclass JniConstants::GetBooleanClass(JNIEnv* env) { 157 EnsureJniConstantsInitialized(env); 158 return booleanClass; 159 } 160 161 jclass JniConstants::GetByteBufferClass(JNIEnv* env) { 162 EnsureJniConstantsInitialized(env); 163 return byteBufferClass; 164 } 165 166 jclass JniConstants::GetDoubleClass(JNIEnv* env) { 167 EnsureJniConstantsInitialized(env); 168 return doubleClass; 169 } 170 171 jclass JniConstants::GetErrnoExceptionClass(JNIEnv* env) { 172 EnsureJniConstantsInitialized(env); 173 return errnoExceptionClass; 174 } 175 176 jclass JniConstants::GetFileDescriptorClass(JNIEnv* env) { 177 EnsureJniConstantsInitialized(env); 178 return fileDescriptorClass; 179 } 180 181 jclass JniConstants::GetGaiExceptionClass(JNIEnv* env) { 182 EnsureJniConstantsInitialized(env); 183 return gaiExceptionClass; 184 } 185 186 jclass JniConstants::GetInet6AddressClass(JNIEnv* env) { 187 EnsureJniConstantsInitialized(env); 188 return inet6AddressClass; 189 } 190 191 jclass JniConstants::GetInet6AddressHolderClass(JNIEnv* env) { 192 EnsureJniConstantsInitialized(env); 193 return inet6AddressHolderClass; 194 } 195 196 jclass JniConstants::GetInetAddressClass(JNIEnv* env) { 197 EnsureJniConstantsInitialized(env); 198 return inetAddressClass; 199 } 200 201 jclass JniConstants::GetInetAddressHolderClass(JNIEnv* env) { 202 EnsureJniConstantsInitialized(env); 203 return inetAddressHolderClass; 204 } 205 206 jclass JniConstants::GetInetSocketAddressClass(JNIEnv* env) { 207 EnsureJniConstantsInitialized(env); 208 return inetSocketAddressClass; 209 } 210 211 jclass JniConstants::GetInetSocketAddressHolderClass(JNIEnv* env) { 212 EnsureJniConstantsInitialized(env); 213 return inetSocketAddressHolderClass; 214 } 215 216 jclass JniConstants::GetIntegerClass(JNIEnv* env) { 217 EnsureJniConstantsInitialized(env); 218 return integerClass; 219 } 220 221 jclass JniConstants::GetLocaleDataClass(JNIEnv* env) { 222 EnsureJniConstantsInitialized(env); 223 return localeDataClass; 224 } 225 226 jclass JniConstants::GetLongClass(JNIEnv* env) { 227 EnsureJniConstantsInitialized(env); 228 return longClass; 229 } 230 231 jclass JniConstants::GetNetlinkSocketAddressClass(JNIEnv* env) { 232 EnsureJniConstantsInitialized(env); 233 return netlinkSocketAddressClass; 234 } 235 236 jclass JniConstants::GetPacketSocketAddressClass(JNIEnv* env) { 237 EnsureJniConstantsInitialized(env); 238 return packetSocketAddressClass; 239 } 240 241 jclass JniConstants::GetVmSocketAddressClass(JNIEnv* env) { 242 EnsureJniConstantsInitialized(env); 243 return vmSocketAddressClass; 244 } 245 246 jclass JniConstants::GetPrimitiveByteArrayClass(JNIEnv* env) { 247 EnsureJniConstantsInitialized(env); 248 return primitiveByteArrayClass; 249 } 250 251 jclass JniConstants::GetStringClass(JNIEnv* env) { 252 EnsureJniConstantsInitialized(env); 253 return stringClass; 254 } 255 256 jclass JniConstants::GetStructAddrinfoClass(JNIEnv* env) { 257 EnsureJniConstantsInitialized(env); 258 return structAddrinfoClass; 259 } 260 261 jclass JniConstants::GetStructCmsghdrClass(JNIEnv* env) { 262 EnsureJniConstantsInitialized(env); 263 return structCmsghdrClass; 264 } 265 266 jclass JniConstants::GetStructGroupReqClass(JNIEnv* env) { 267 EnsureJniConstantsInitialized(env); 268 return structGroupReqClass; 269 } 270 271 jclass JniConstants::GetStructIfaddrsClass(JNIEnv* env) { 272 EnsureJniConstantsInitialized(env); 273 return structIfaddrsClass; 274 } 275 276 jclass JniConstants::GetStructLingerClass(JNIEnv* env) { 277 EnsureJniConstantsInitialized(env); 278 return structLingerClass; 279 } 280 281 jclass JniConstants::GetStructMsghdrClass(JNIEnv* env) { 282 EnsureJniConstantsInitialized(env); 283 return structMsghdrClass; 284 } 285 286 jclass JniConstants::GetStructPasswdClass(JNIEnv* env) { 287 EnsureJniConstantsInitialized(env); 288 return structPasswdClass; 289 } 290 291 jclass JniConstants::GetStructPollfdClass(JNIEnv* env) { 292 EnsureJniConstantsInitialized(env); 293 return structPollfdClass; 294 } 295 296 jclass JniConstants::GetStructStatClass(JNIEnv* env) { 297 EnsureJniConstantsInitialized(env); 298 return structStatClass; 299 } 300 301 jclass JniConstants::GetStructStatVfsClass(JNIEnv* env) { 302 EnsureJniConstantsInitialized(env); 303 return structStatVfsClass; 304 } 305 306 jclass JniConstants::GetStructTimespecClass(JNIEnv* env) { 307 EnsureJniConstantsInitialized(env); 308 return structTimespecClass; 309 } 310 311 jclass JniConstants::GetStructTimevalClass(JNIEnv* env) { 312 EnsureJniConstantsInitialized(env); 313 return structTimevalClass; 314 } 315 316 jclass JniConstants::GetStructUcredClass(JNIEnv* env) { 317 EnsureJniConstantsInitialized(env); 318 return structUcredClass; 319 } 320 321 jclass JniConstants::GetStructUtsnameClass(JNIEnv* env) { 322 EnsureJniConstantsInitialized(env); 323 return structUtsnameClass; 324 } 325 326 jclass JniConstants::GetUnixSocketAddressClass(JNIEnv* env) { 327 EnsureJniConstantsInitialized(env); 328 return unixSocketAddressClass; 329 } 330