| /* |
| * 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 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"); |
| 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::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; |
| } |