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