/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "JniConstants" #include "JniConstants.h" #include #include #include #include #include namespace { jclass findClass(JNIEnv* env, const char* name) { ScopedLocalRef localClass(env, env->FindClass(name)); jclass result = reinterpret_cast(env->NewGlobalRef(localClass.get())); if (result == NULL) { ALOGE("failed to find class '%s'", name); abort(); } return result; } // Mutex protecting static variables static std::mutex g_constants_mutex; // Flag indicating whether cached constants are valid static bool g_constants_valid = false; // Constants jclass booleanClass; jclass byteBufferClass; jclass doubleClass; jclass errnoExceptionClass; jclass fileDescriptorClass; jclass gaiExceptionClass; jclass inet6AddressClass; jclass inet6AddressHolderClass; jclass inetAddressClass; jclass inetAddressHolderClass; jclass inetSocketAddressClass; jclass inetSocketAddressHolderClass; jclass integerClass; jclass localeDataClass; jclass longClass; jclass netlinkSocketAddressClass; jclass packetSocketAddressClass; jclass vmSocketAddressClass; jclass primitiveByteArrayClass; jclass stringClass; jclass structAddrinfoClass; jclass structCmsghdrClass; jclass structGroupReqClass; jclass structIfaddrsClass; jclass structLingerClass; jclass structMsghdrClass; jclass structPasswdClass; jclass structPollfdClass; jclass structStatClass; jclass structStatVfsClass; jclass structTimespecClass; jclass structTimevalClass; jclass structUcredClass; jclass structUtsnameClass; jclass unixSocketAddressClass; // EnsureJniConstantsInitialized initializes cached constants. It should be // called before returning a heap object from the cache to ensure cache is // initialized. This pattern is only necessary because if a process finishes one // runtime and starts another then JNI_OnLoad may not be called. void EnsureJniConstantsInitialized(JNIEnv* env) { if (g_constants_valid) { return; } std::lock_guard guard(g_constants_mutex); if (g_constants_valid) { return; } booleanClass = findClass(env, "java/lang/Boolean"); byteBufferClass = findClass(env, "java/nio/ByteBuffer"); doubleClass = findClass(env, "java/lang/Double"); errnoExceptionClass = findClass(env, "android/system/ErrnoException"); fileDescriptorClass = findClass(env, "java/io/FileDescriptor"); gaiExceptionClass = findClass(env, "android/system/GaiException"); inet6AddressClass = findClass(env, "java/net/Inet6Address"); inet6AddressHolderClass = findClass(env, "java/net/Inet6Address$Inet6AddressHolder"); inetAddressClass = findClass(env, "java/net/InetAddress"); inetAddressHolderClass = findClass(env, "java/net/InetAddress$InetAddressHolder"); inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress"); inetSocketAddressHolderClass = findClass(env, "java/net/InetSocketAddress$InetSocketAddressHolder"); integerClass = findClass(env, "java/lang/Integer"); localeDataClass = findClass(env, "libcore/icu/LocaleData"); longClass = findClass(env, "java/lang/Long"); netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress"); packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress"); vmSocketAddressClass = findClass(env, "android/system/VmSocketAddress"); primitiveByteArrayClass = findClass(env, "[B"); stringClass = findClass(env, "java/lang/String"); structAddrinfoClass = findClass(env, "android/system/StructAddrinfo"); structCmsghdrClass = findClass(env, "android/system/StructCmsghdr"); structGroupReqClass = findClass(env, "android/system/StructGroupReq"); structIfaddrsClass = findClass(env, "android/system/StructIfaddrs"); structLingerClass = findClass(env, "android/system/StructLinger"); structMsghdrClass = findClass(env, "android/system/StructMsghdr"); structPasswdClass = findClass(env, "android/system/StructPasswd"); structPollfdClass = findClass(env, "android/system/StructPollfd"); structStatClass = findClass(env, "android/system/StructStat"); structStatVfsClass = findClass(env, "android/system/StructStatVfs"); structTimevalClass = findClass(env, "android/system/StructTimeval"); structTimespecClass = findClass(env, "android/system/StructTimespec"); structUcredClass = findClass(env, "android/system/StructUcred"); structUtsnameClass = findClass(env, "android/system/StructUtsname"); unixSocketAddressClass = findClass(env, "android/system/UnixSocketAddress"); g_constants_valid = true; } } // namespace void JniConstants::Initialize(JNIEnv* env) { EnsureJniConstantsInitialized(env); } void JniConstants::Invalidate() { // This method is called when a new runtime instance is created. There is no // notification of a runtime instance being destroyed in the JNI interface // so we piggyback on creation. Since only one runtime is supported at a // time, we know the constants are invalid when JNI_CreateJavaVM() is // called. // // Clean shutdown would require calling DeleteGlobalRef() for each of the // class references, but JavaVM is unavailable because ART only calls this // once all threads are unregistered. std::lock_guard guard(g_constants_mutex); g_constants_valid = false; } jclass JniConstants::GetBooleanClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return booleanClass; } jclass JniConstants::GetByteBufferClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return byteBufferClass; } jclass JniConstants::GetDoubleClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return doubleClass; } jclass JniConstants::GetErrnoExceptionClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return errnoExceptionClass; } jclass JniConstants::GetFileDescriptorClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return fileDescriptorClass; } jclass JniConstants::GetGaiExceptionClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return gaiExceptionClass; } jclass JniConstants::GetInet6AddressClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return inet6AddressClass; } jclass JniConstants::GetInet6AddressHolderClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return inet6AddressHolderClass; } jclass JniConstants::GetInetAddressClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return inetAddressClass; } jclass JniConstants::GetInetAddressHolderClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return inetAddressHolderClass; } jclass JniConstants::GetInetSocketAddressClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return inetSocketAddressClass; } jclass JniConstants::GetInetSocketAddressHolderClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return inetSocketAddressHolderClass; } jclass JniConstants::GetIntegerClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return integerClass; } jclass JniConstants::GetLocaleDataClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return localeDataClass; } jclass JniConstants::GetLongClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return longClass; } jclass JniConstants::GetNetlinkSocketAddressClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return netlinkSocketAddressClass; } jclass JniConstants::GetPacketSocketAddressClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return packetSocketAddressClass; } jclass JniConstants::GetVmSocketAddressClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return vmSocketAddressClass; } jclass JniConstants::GetPrimitiveByteArrayClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return primitiveByteArrayClass; } jclass JniConstants::GetStringClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return stringClass; } jclass JniConstants::GetStructAddrinfoClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structAddrinfoClass; } jclass JniConstants::GetStructCmsghdrClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structCmsghdrClass; } jclass JniConstants::GetStructGroupReqClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structGroupReqClass; } jclass JniConstants::GetStructIfaddrsClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structIfaddrsClass; } jclass JniConstants::GetStructLingerClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structLingerClass; } jclass JniConstants::GetStructMsghdrClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structMsghdrClass; } jclass JniConstants::GetStructPasswdClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structPasswdClass; } jclass JniConstants::GetStructPollfdClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structPollfdClass; } jclass JniConstants::GetStructStatClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structStatClass; } jclass JniConstants::GetStructStatVfsClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structStatVfsClass; } jclass JniConstants::GetStructTimespecClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structTimespecClass; } jclass JniConstants::GetStructTimevalClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structTimevalClass; } jclass JniConstants::GetStructUcredClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structUcredClass; } jclass JniConstants::GetStructUtsnameClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structUtsnameClass; } jclass JniConstants::GetUnixSocketAddressClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return unixSocketAddressClass; }