1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #pragma once 4 5 #include <fbjni/fbjni.h> 6 7 #include <memory> 8 #include <unordered_map> 9 10 namespace jni = facebook::jni; 11 12 namespace expo { 13 14 template <typename T> 15 inline void hash_combine(std::size_t& seed, const T& v) 16 { 17 std::hash<T> hasher; 18 // Reference from: https://github.com/boostorg/container_hash/blob/boost-1.76.0/include/boost/container_hash/hash.hpp 19 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 20 } 21 22 struct pairhash { 23 template <typename A, typename B> 24 std::size_t operator()(const std::pair<A, B>& v) const { 25 std::size_t seed = 0; 26 hash_combine(seed, v.first); 27 hash_combine(seed, v.second); 28 return seed; 29 } 30 }; 31 32 using MethodHashMap = std::unordered_map<std::pair<std::string, std::string>, jmethodID, pairhash>; 33 34 /** 35 * Singleton registry used to store references to often used Java classes. 36 */ 37 class JavaReferencesCache { 38 public: 39 /** 40 * An entry in the Java class registry. 41 */ 42 class CachedJClass { 43 public: 44 CachedJClass(jclass clazz, MethodHashMap methods); 45 46 /** 47 * A bare reference to the class object. 48 */ 49 jclass clazz; 50 51 /** 52 * Returns a cached method id for provided method name and signature. 53 */ 54 jmethodID getMethod(const std::string &name, const std::string &signature); 55 56 private: 57 MethodHashMap methods; 58 }; 59 60 JavaReferencesCache(JavaReferencesCache const &) = delete; 61 62 JavaReferencesCache &operator=(JavaReferencesCache const &) = delete; 63 64 /** 65 * Gets a singleton instance 66 */ 67 static std::shared_ptr<JavaReferencesCache> instance(); 68 69 /** 70 * Gets a cached Java class entry. 71 */ 72 CachedJClass &getJClass(const std::string &className); 73 74 /** 75 * Gets a cached Java class entry or loads it to the registry. 76 */ 77 CachedJClass &getOrLoadJClass(JNIEnv *env, const std::string &className); 78 79 /** 80 * Loads predefined set of Java classes and stores them 81 */ 82 void loadJClasses(JNIEnv *env); 83 84 private: 85 JavaReferencesCache() = default; 86 87 std::unordered_map<std::string, CachedJClass> jClassRegistry; 88 89 void loadJClass( 90 JNIEnv *env, 91 const std::string &name, 92 const std::vector<std::pair<std::string, std::string>> &methods 93 ); 94 }; 95 } // namespace expo 96