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