1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "JniConstants.h" 18 19 #include <pthread.h> 20 #include <stdbool.h> 21 #include <stddef.h> 22 #include <string.h> 23 24 #define LOG_TAG "JniConstants" 25 #include "ALog-priv.h" 26 27 // jclass constants list: 28 // <class, signature, androidOnly> 29 30 #define JCLASS_CONSTANTS_LIST(V) \ 31 V(FileDescriptor, "java/io/FileDescriptor", false) \ 32 V(NIOAccess, "java/nio/NIOAccess", true) \ 33 V(NioBuffer, "java/nio/Buffer", false) 34 35 // jmethodID's of public methods constants list: 36 // <Class, method, method-string, signature, is_static> 37 #define JMETHODID_CONSTANTS_LIST(V) \ 38 V(FileDescriptor, init, "<init>", "()V", false) \ 39 V(NIOAccess, getBaseArray, "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;", true) \ 40 V(NIOAccess, getBaseArrayOffset, "getBaseArrayOffset", "(Ljava/nio/Buffer;)I", true) \ 41 V(NioBuffer, array, "array", "()Ljava/lang/Object;", false) \ 42 V(NioBuffer, arrayOffset, "arrayOffset", "()I", false) 43 44 // jfieldID constants list: 45 // <Class, field, signature, is_static> 46 #define JFIELDID_CONSTANTS_LIST(V) \ 47 V(FileDescriptor, descriptor, "I", false) \ 48 V(NioBuffer, _elementSizeShift, "I", false) \ 49 V(NioBuffer, address, "J", false) \ 50 V(NioBuffer, limit, "I", false) \ 51 V(NioBuffer, position, "I", false) 52 53 #define CLASS_NAME(cls) g_ ## cls 54 #define METHOD_NAME(cls, method) g_ ## cls ## _ ## method 55 #define FIELD_NAME(cls, field) g_ ## cls ## _ ## field 56 57 // 58 // Declare storage for cached classes, methods and fields. 59 // 60 61 #define JCLASS_DECLARE_STORAGE(cls, ...) \ 62 static jclass CLASS_NAME(cls) = NULL; 63 JCLASS_CONSTANTS_LIST(JCLASS_DECLARE_STORAGE) 64 #undef JCLASS_DECLARE_STORAGE 65 66 #define JMETHODID_DECLARE_STORAGE(cls, method, ...) \ 67 static jmethodID METHOD_NAME(cls, method) = NULL; 68 JMETHODID_CONSTANTS_LIST(JMETHODID_DECLARE_STORAGE) 69 #undef JMETHODID_DECLARE_STORAGE 70 71 #define JFIELDID_DECLARE_STORAGE(cls, field, ...) \ 72 static jfieldID FIELD_NAME(cls, field) = NULL; 73 JFIELDID_CONSTANTS_LIST(JFIELDID_DECLARE_STORAGE) 74 #undef JFIELDID_DECLARE_STORAGE 75 76 // 77 // Helper methods 78 // 79 80 static jclass FindClass(JNIEnv* env, const char* signature, bool androidOnly) { 81 jclass cls = (*env)->FindClass(env, signature); 82 if (cls == NULL) { 83 ALOG_ALWAYS_FATAL_IF(!androidOnly, "Class not found: %s", signature); 84 return NULL; 85 } 86 return (*env)->NewGlobalRef(env, cls); 87 } 88 89 static jmethodID FindMethod(JNIEnv* env, jclass cls, 90 const char* name, const char* signature, bool isStatic) { 91 jmethodID method; 92 if (isStatic) { 93 method = (*env)->GetStaticMethodID(env, cls, name, signature); 94 } else { 95 method = (*env)->GetMethodID(env, cls, name, signature); 96 } 97 ALOG_ALWAYS_FATAL_IF(method == NULL, "Method not found: %s:%s", name, signature); 98 return method; 99 } 100 101 static jfieldID FindField(JNIEnv* env, jclass cls, 102 const char* name, const char* signature, bool isStatic) { 103 jfieldID field; 104 if (isStatic) { 105 field = (*env)->GetStaticFieldID(env, cls, name, signature); 106 } else { 107 field = (*env)->GetFieldID(env, cls, name, signature); 108 } 109 ALOG_ALWAYS_FATAL_IF(field == NULL, "Field not found: %s:%s", name, signature); 110 return field; 111 } 112 113 static pthread_once_t g_initialized = PTHREAD_ONCE_INIT; 114 static JNIEnv* g_init_env; 115 116 static void InitializeConstants() { 117 // Initialize cached classes. 118 #define JCLASS_INITIALIZE(cls, signature, androidOnly) \ 119 CLASS_NAME(cls) = FindClass(g_init_env, signature, androidOnly); 120 JCLASS_CONSTANTS_LIST(JCLASS_INITIALIZE) 121 #undef JCLASS_INITIALIZE 122 123 // Initialize cached methods. 124 #define JMETHODID_INITIALIZE(cls, method, name, signature, isStatic) \ 125 METHOD_NAME(cls, method) = \ 126 FindMethod(g_init_env, CLASS_NAME(cls), name, signature, isStatic); 127 JMETHODID_CONSTANTS_LIST(JMETHODID_INITIALIZE) 128 #undef JMETHODID_INITIALIZE 129 130 // Initialize cached fields. 131 #define JFIELDID_INITIALIZE(cls, field, signature, isStatic) \ 132 FIELD_NAME(cls, field) = \ 133 FindField(g_init_env, CLASS_NAME(cls), #field, signature, isStatic); 134 JFIELDID_CONSTANTS_LIST(JFIELDID_INITIALIZE) 135 #undef JFIELDID_INITIALIZE 136 } 137 138 void EnsureInitialized(JNIEnv* env) { 139 // This method has to be called in every cache accesses because library can be built 140 // 2 different ways and existing usage for compat version doesn't have a good hook for 141 // initialization and is widely used. 142 g_init_env = env; 143 pthread_once(&g_initialized, InitializeConstants); 144 } 145 146 // API exported by libnativehelper_api.h. 147 148 void jniUninitializeConstants() { 149 // Uninitialize cached classes, methods and fields. 150 // 151 // NB we assume the runtime is stopped at this point and do not delete global 152 // references. 153 #define JCLASS_INVALIDATE(cls, ...) CLASS_NAME(cls) = NULL; 154 JCLASS_CONSTANTS_LIST(JCLASS_INVALIDATE); 155 #undef JCLASS_INVALIDATE 156 157 #define JMETHODID_INVALIDATE(cls, method, ...) METHOD_NAME(cls, method) = NULL; 158 JMETHODID_CONSTANTS_LIST(JMETHODID_INVALIDATE); 159 #undef JMETHODID_INVALIDATE 160 161 #define JFIELDID_INVALIDATE(cls, field, ...) FIELD_NAME(cls, field) = NULL; 162 JFIELDID_CONSTANTS_LIST(JFIELDID_INVALIDATE); 163 #undef JFIELDID_INVALIDATE 164 165 // If jniConstantsUninitialize is called, runtime has shutdown. Reset 166 // state as some tests re-start the runtime. 167 pthread_once_t o = PTHREAD_ONCE_INIT; 168 memcpy(&g_initialized, &o, sizeof(o)); 169 } 170 171 // 172 // Accessors 173 // 174 175 #define JCLASS_ACCESSOR_IMPL(cls, ...) \ 176 jclass JniConstants_ ## cls ## Class(JNIEnv* env) { \ 177 EnsureInitialized(env); \ 178 return CLASS_NAME(cls); \ 179 } 180 JCLASS_CONSTANTS_LIST(JCLASS_ACCESSOR_IMPL) 181 #undef JCLASS_ACCESSOR_IMPL 182 183 #define JMETHODID_ACCESSOR_IMPL(cls, method, ...) \ 184 jmethodID JniConstants_ ## cls ## _ ## method(JNIEnv* env) { \ 185 EnsureInitialized(env); \ 186 return METHOD_NAME(cls, method); \ 187 } 188 JMETHODID_CONSTANTS_LIST(JMETHODID_ACCESSOR_IMPL) 189 190 #define JFIELDID_ACCESSOR_IMPL(cls, field, ...) \ 191 jfieldID JniConstants_ ## cls ## _ ## field(JNIEnv* env) { \ 192 EnsureInitialized(env); \ 193 return FIELD_NAME(cls, field); \ 194 } 195 JFIELDID_CONSTANTS_LIST(JFIELDID_ACCESSOR_IMPL) 196