1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #include "JavaReferencesCache.h" 4 5 namespace expo { 6 std::shared_ptr<JavaReferencesCache> JavaReferencesCache::instance() { 7 static std::shared_ptr<JavaReferencesCache> singleton{new JavaReferencesCache}; 8 return singleton; 9 } 10 11 void JavaReferencesCache::loadJClasses(JNIEnv *env) { 12 loadJClass(env, "java/lang/Double", { 13 {"<init>", "(D)V"} 14 }); 15 16 loadJClass(env, "java/lang/Boolean", { 17 {"<init>", "(Z)V"} 18 }); 19 20 loadJClass(env, "java/lang/Integer", { 21 {"<init>", "(I)V"} 22 }); 23 24 loadJClass(env, "java/lang/Float", { 25 {"<init>", "(F)V"} 26 }); 27 28 loadJClass(env, "com/facebook/react/bridge/PromiseImpl", { 29 {"<init>", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V"} 30 }); 31 32 loadJClass(env, "java/lang/Object", {}); 33 loadJClass(env, "java/lang/String", {}); 34 loadJClass(env, "expo/modules/kotlin/jni/JavaScriptObject", {}); 35 loadJClass(env, "expo/modules/kotlin/jni/JavaScriptValue", {}); 36 loadJClass(env, "expo/modules/kotlin/jni/JavaScriptTypedArray", {}); 37 loadJClass(env, "com/facebook/react/bridge/ReadableNativeArray", {}); 38 loadJClass(env, "com/facebook/react/bridge/ReadableNativeMap", {}); 39 } 40 41 void JavaReferencesCache::loadJClass( 42 JNIEnv *env, 43 const std::string &name, 44 const std::vector<std::pair<std::string, std::string>> &methodsNames 45 ) { 46 // Note this clazz variable points to a leaked global reference. 47 // This is appropriate for classes that are never unloaded which is any class in an Android app. 48 auto clazz = (jclass) env->NewGlobalRef(env->FindClass(name.c_str())); 49 50 MethodHashMap methods; 51 methods.reserve(methodsNames.size()); 52 53 for (auto &method: methodsNames) { 54 methods.insert( 55 {method, env->GetMethodID(clazz, method.first.c_str(), method.second.c_str())} 56 ); 57 } 58 59 jClassRegistry.insert( 60 {name, CachedJClass(clazz, std::move(methods))} 61 ); 62 } 63 64 JavaReferencesCache::CachedJClass &JavaReferencesCache::getJClass( 65 const std::string &className 66 ) { 67 return jClassRegistry.at(className); 68 } 69 70 JavaReferencesCache::CachedJClass &JavaReferencesCache::getOrLoadJClass( 71 JNIEnv *env, 72 const std::string &className 73 ) { 74 auto result = jClassRegistry.find(className); 75 if (result == jClassRegistry.end()) { 76 loadJClass(env, className, {}); 77 return jClassRegistry.at(className); 78 } 79 80 return result->second; 81 } 82 83 jmethodID JavaReferencesCache::CachedJClass::getMethod( 84 const std::string &name, 85 const std::string &signature 86 ) { 87 return methods.at({name, signature}); 88 } 89 90 JavaReferencesCache::CachedJClass::CachedJClass( 91 jclass clazz, 92 MethodHashMap methods 93 ) : clazz(clazz), methods(std::move(methods)) {} 94 } // namespace expo 95