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, "com/facebook/react/bridge/PromiseImpl", { 21 {"<init>", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V"} 22 }); 23 24 loadJClass(env, "java/lang/Object", {}); 25 } 26 27 void JavaReferencesCache::loadJClass( 28 JNIEnv *env, 29 const std::string &name, 30 const std::vector<std::pair<std::string, std::string>> &methodsNames 31 ) { 32 // Note this clazz variable points to a leaked global reference. 33 // This is appropriate for classes that are never unloaded which is any class in an Android app. 34 auto clazz = (jclass) env->NewGlobalRef(env->FindClass(name.c_str())); 35 36 MethodHashMap methods; 37 methods.reserve(methodsNames.size()); 38 39 for (auto &method: methodsNames) { 40 methods.insert( 41 {method, env->GetMethodID(clazz, method.first.c_str(), method.second.c_str())} 42 ); 43 } 44 45 jClassRegistry.insert( 46 {name, CachedJClass(clazz, std::move(methods))} 47 ); 48 } 49 50 JavaReferencesCache::CachedJClass &JavaReferencesCache::getJClass( 51 const std::string &className 52 ) { 53 return jClassRegistry.at(className); 54 } 55 56 jmethodID JavaReferencesCache::CachedJClass::getMethod( 57 const std::string &name, 58 const std::string &signature 59 ) { 60 return methods.at({name, signature}); 61 } 62 63 JavaReferencesCache::CachedJClass::CachedJClass( 64 jclass clazz, 65 MethodHashMap methods 66 ) : clazz(clazz), methods(std::move(methods)) {} 67 } // namespace expo 68