// Copyright © 2021-present 650 Industries, Inc. (aka Expo) #include "JavaReferencesCache.h" #include namespace expo { std::shared_ptr JavaReferencesCache::instance() { static std::shared_ptr singleton{new JavaReferencesCache}; return singleton; } void JavaReferencesCache::loadJClasses(JNIEnv *env) { loadJClass(env, "java/lang/Double", { {"", "(D)V"} }); loadJClass(env, "java/lang/Boolean", { {"", "(Z)V"} }); loadJClass(env, "java/lang/Integer", { {"", "(I)V"} }); loadJClass(env, "java/lang/Long", { {"", "(J)V"} }); loadJClass(env, "java/lang/Float", { {"", "(F)V"} }); loadJClass(env, "com/facebook/react/bridge/PromiseImpl", { {"", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V"} }); loadJClass(env, "expo/modules/kotlin/jni/PromiseImpl", { {"", "(Lexpo/modules/kotlin/jni/JavaCallback;Lexpo/modules/kotlin/jni/JavaCallback;)V"} }); loadJClass(env, "java/lang/Object", {}); loadJClass(env, "java/lang/String", {}); loadJClass(env, "expo/modules/kotlin/jni/JavaScriptObject", {}); loadJClass(env, "expo/modules/kotlin/jni/JavaScriptValue", {}); loadJClass(env, "expo/modules/kotlin/jni/JavaScriptTypedArray", {}); loadJClass(env, "com/facebook/react/bridge/ReadableNativeArray", {}); loadJClass(env, "com/facebook/react/bridge/ReadableNativeMap", {}); loadJClass(env, "com/facebook/react/bridge/WritableNativeArray", {}); loadJClass(env, "com/facebook/react/bridge/WritableNativeMap", {}); loadJClass(env, "expo/modules/kotlin/sharedobjects/SharedObject", {}); } void JavaReferencesCache::loadJClass( JNIEnv *env, const std::string &name, const std::vector> &methodsNames ) { // Note this clazz variable points to a leaked global reference. // This is appropriate for classes that are never unloaded which is any class in an Android app. auto clazz = (jclass) env->NewGlobalRef(env->FindClass(name.c_str())); MethodHashMap methods; methods.reserve(methodsNames.size()); for (auto &method: methodsNames) { methods.insert( {method, env->GetMethodID(clazz, method.first.c_str(), method.second.c_str())} ); } jClassRegistry.insert( {name, CachedJClass(clazz, std::move(methods))} ); } JavaReferencesCache::CachedJClass &JavaReferencesCache::getJClass( const std::string &className ) { return jClassRegistry.at(className); } JavaReferencesCache::CachedJClass &JavaReferencesCache::getOrLoadJClass( JNIEnv *env, const std::string &className ) { auto result = jClassRegistry.find(className); if (result == jClassRegistry.end()) { loadJClass(env, className, {}); return jClassRegistry.at(className); } return result->second; } jmethodID JavaReferencesCache::CachedJClass::getMethod( const std::string &name, const std::string &signature ) { return methods.at({name, signature}); } JavaReferencesCache::CachedJClass::CachedJClass( jclass clazz, MethodHashMap methods ) : clazz(clazz), methods(std::move(methods)) {} } // namespace expo