196 lines
7.6 KiB
C
196 lines
7.6 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
|
|
#include "JniConstants.h"
|
|
|
|
#include <pthread.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#define LOG_TAG "JniConstants"
|
|
#include "ALog-priv.h"
|
|
|
|
// jclass constants list:
|
|
// <class, signature, androidOnly>
|
|
|
|
#define JCLASS_CONSTANTS_LIST(V) \
|
|
V(FileDescriptor, "java/io/FileDescriptor", false) \
|
|
V(NIOAccess, "java/nio/NIOAccess", true) \
|
|
V(NioBuffer, "java/nio/Buffer", false)
|
|
|
|
// jmethodID's of public methods constants list:
|
|
// <Class, method, method-string, signature, is_static>
|
|
#define JMETHODID_CONSTANTS_LIST(V) \
|
|
V(FileDescriptor, init, "<init>", "()V", false) \
|
|
V(NIOAccess, getBaseArray, "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;", true) \
|
|
V(NIOAccess, getBaseArrayOffset, "getBaseArrayOffset", "(Ljava/nio/Buffer;)I", true) \
|
|
V(NioBuffer, array, "array", "()Ljava/lang/Object;", false) \
|
|
V(NioBuffer, arrayOffset, "arrayOffset", "()I", false)
|
|
|
|
// jfieldID constants list:
|
|
// <Class, field, signature, is_static>
|
|
#define JFIELDID_CONSTANTS_LIST(V) \
|
|
V(FileDescriptor, descriptor, "I", false) \
|
|
V(NioBuffer, _elementSizeShift, "I", false) \
|
|
V(NioBuffer, address, "J", false) \
|
|
V(NioBuffer, limit, "I", false) \
|
|
V(NioBuffer, position, "I", false)
|
|
|
|
#define CLASS_NAME(cls) g_ ## cls
|
|
#define METHOD_NAME(cls, method) g_ ## cls ## _ ## method
|
|
#define FIELD_NAME(cls, field) g_ ## cls ## _ ## field
|
|
|
|
//
|
|
// Declare storage for cached classes, methods and fields.
|
|
//
|
|
|
|
#define JCLASS_DECLARE_STORAGE(cls, ...) \
|
|
static jclass CLASS_NAME(cls) = NULL;
|
|
JCLASS_CONSTANTS_LIST(JCLASS_DECLARE_STORAGE)
|
|
#undef JCLASS_DECLARE_STORAGE
|
|
|
|
#define JMETHODID_DECLARE_STORAGE(cls, method, ...) \
|
|
static jmethodID METHOD_NAME(cls, method) = NULL;
|
|
JMETHODID_CONSTANTS_LIST(JMETHODID_DECLARE_STORAGE)
|
|
#undef JMETHODID_DECLARE_STORAGE
|
|
|
|
#define JFIELDID_DECLARE_STORAGE(cls, field, ...) \
|
|
static jfieldID FIELD_NAME(cls, field) = NULL;
|
|
JFIELDID_CONSTANTS_LIST(JFIELDID_DECLARE_STORAGE)
|
|
#undef JFIELDID_DECLARE_STORAGE
|
|
|
|
//
|
|
// Helper methods
|
|
//
|
|
|
|
static jclass FindClass(JNIEnv* env, const char* signature, bool androidOnly) {
|
|
jclass cls = (*env)->FindClass(env, signature);
|
|
if (cls == NULL) {
|
|
ALOG_ALWAYS_FATAL_IF(!androidOnly, "Class not found: %s", signature);
|
|
return NULL;
|
|
}
|
|
return (*env)->NewGlobalRef(env, cls);
|
|
}
|
|
|
|
static jmethodID FindMethod(JNIEnv* env, jclass cls,
|
|
const char* name, const char* signature, bool isStatic) {
|
|
jmethodID method;
|
|
if (isStatic) {
|
|
method = (*env)->GetStaticMethodID(env, cls, name, signature);
|
|
} else {
|
|
method = (*env)->GetMethodID(env, cls, name, signature);
|
|
}
|
|
ALOG_ALWAYS_FATAL_IF(method == NULL, "Method not found: %s:%s", name, signature);
|
|
return method;
|
|
}
|
|
|
|
static jfieldID FindField(JNIEnv* env, jclass cls,
|
|
const char* name, const char* signature, bool isStatic) {
|
|
jfieldID field;
|
|
if (isStatic) {
|
|
field = (*env)->GetStaticFieldID(env, cls, name, signature);
|
|
} else {
|
|
field = (*env)->GetFieldID(env, cls, name, signature);
|
|
}
|
|
ALOG_ALWAYS_FATAL_IF(field == NULL, "Field not found: %s:%s", name, signature);
|
|
return field;
|
|
}
|
|
|
|
static pthread_once_t g_initialized = PTHREAD_ONCE_INIT;
|
|
static JNIEnv* g_init_env;
|
|
|
|
static void InitializeConstants() {
|
|
// Initialize cached classes.
|
|
#define JCLASS_INITIALIZE(cls, signature, androidOnly) \
|
|
CLASS_NAME(cls) = FindClass(g_init_env, signature, androidOnly);
|
|
JCLASS_CONSTANTS_LIST(JCLASS_INITIALIZE)
|
|
#undef JCLASS_INITIALIZE
|
|
|
|
// Initialize cached methods.
|
|
#define JMETHODID_INITIALIZE(cls, method, name, signature, isStatic) \
|
|
METHOD_NAME(cls, method) = \
|
|
FindMethod(g_init_env, CLASS_NAME(cls), name, signature, isStatic);
|
|
JMETHODID_CONSTANTS_LIST(JMETHODID_INITIALIZE)
|
|
#undef JMETHODID_INITIALIZE
|
|
|
|
// Initialize cached fields.
|
|
#define JFIELDID_INITIALIZE(cls, field, signature, isStatic) \
|
|
FIELD_NAME(cls, field) = \
|
|
FindField(g_init_env, CLASS_NAME(cls), #field, signature, isStatic);
|
|
JFIELDID_CONSTANTS_LIST(JFIELDID_INITIALIZE)
|
|
#undef JFIELDID_INITIALIZE
|
|
}
|
|
|
|
void EnsureInitialized(JNIEnv* env) {
|
|
// This method has to be called in every cache accesses because library can be built
|
|
// 2 different ways and existing usage for compat version doesn't have a good hook for
|
|
// initialization and is widely used.
|
|
g_init_env = env;
|
|
pthread_once(&g_initialized, InitializeConstants);
|
|
}
|
|
|
|
// API exported by libnativehelper_api.h.
|
|
|
|
void jniUninitializeConstants() {
|
|
// Uninitialize cached classes, methods and fields.
|
|
//
|
|
// NB we assume the runtime is stopped at this point and do not delete global
|
|
// references.
|
|
#define JCLASS_INVALIDATE(cls, ...) CLASS_NAME(cls) = NULL;
|
|
JCLASS_CONSTANTS_LIST(JCLASS_INVALIDATE);
|
|
#undef JCLASS_INVALIDATE
|
|
|
|
#define JMETHODID_INVALIDATE(cls, method, ...) METHOD_NAME(cls, method) = NULL;
|
|
JMETHODID_CONSTANTS_LIST(JMETHODID_INVALIDATE);
|
|
#undef JMETHODID_INVALIDATE
|
|
|
|
#define JFIELDID_INVALIDATE(cls, field, ...) FIELD_NAME(cls, field) = NULL;
|
|
JFIELDID_CONSTANTS_LIST(JFIELDID_INVALIDATE);
|
|
#undef JFIELDID_INVALIDATE
|
|
|
|
// If jniConstantsUninitialize is called, runtime has shutdown. Reset
|
|
// state as some tests re-start the runtime.
|
|
pthread_once_t o = PTHREAD_ONCE_INIT;
|
|
memcpy(&g_initialized, &o, sizeof(o));
|
|
}
|
|
|
|
//
|
|
// Accessors
|
|
//
|
|
|
|
#define JCLASS_ACCESSOR_IMPL(cls, ...) \
|
|
jclass JniConstants_ ## cls ## Class(JNIEnv* env) { \
|
|
EnsureInitialized(env); \
|
|
return CLASS_NAME(cls); \
|
|
}
|
|
JCLASS_CONSTANTS_LIST(JCLASS_ACCESSOR_IMPL)
|
|
#undef JCLASS_ACCESSOR_IMPL
|
|
|
|
#define JMETHODID_ACCESSOR_IMPL(cls, method, ...) \
|
|
jmethodID JniConstants_ ## cls ## _ ## method(JNIEnv* env) { \
|
|
EnsureInitialized(env); \
|
|
return METHOD_NAME(cls, method); \
|
|
}
|
|
JMETHODID_CONSTANTS_LIST(JMETHODID_ACCESSOR_IMPL)
|
|
|
|
#define JFIELDID_ACCESSOR_IMPL(cls, field, ...) \
|
|
jfieldID JniConstants_ ## cls ## _ ## field(JNIEnv* env) { \
|
|
EnsureInitialized(env); \
|
|
return FIELD_NAME(cls, field); \
|
|
}
|
|
JFIELDID_CONSTANTS_LIST(JFIELDID_ACCESSOR_IMPL)
|