/* * 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 <atomic> #include <mutex> #include <stdlib.h> #include <log/log.h> #include <nativehelper/ScopedLocalRef.h> namespace { jclass findClass(JNIEnv* env, const char* name) { ScopedLocalRef<jclass> localClass(env, env->FindClass(name)); jclass result = reinterpret_cast<jclass>(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 charsetICUClass; 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 patternSyntaxExceptionClass; jclass stringClass; jclass structAddrinfoClass; jclass structFlockClass; jclass structGroupReqClass; jclass structIfaddrsClass; jclass structLingerClass; 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"); charsetICUClass = findClass(env, "java/nio/charset/CharsetICU"); 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"); patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException"); stringClass = findClass(env, "java/lang/String"); structAddrinfoClass = findClass(env, "android/system/StructAddrinfo"); structFlockClass = findClass(env, "android/system/StructFlock"); structGroupReqClass = findClass(env, "android/system/StructGroupReq"); structIfaddrsClass = findClass(env, "android/system/StructIfaddrs"); structLingerClass = findClass(env, "android/system/StructLinger"); 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() { std::lock_guard guard(g_constants_mutex); g_constants_valid = false; } jclass JniConstants::GetBooleanClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return booleanClass; } jclass JniConstants::GetCharsetICUClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return charsetICUClass; } 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::GetPatternSyntaxExceptionClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return patternSyntaxExceptionClass; } jclass JniConstants::GetStringClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return stringClass; } jclass JniConstants::GetStructAddrinfoClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structAddrinfoClass; } jclass JniConstants::GetStructFlockClass(JNIEnv* env) { EnsureJniConstantsInitialized(env); return structFlockClass; } 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::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; }