@@ -723,16 +723,31 @@ jclass JEnv::FindClass(const string &className) {
723723 jclass global_class = CheckForClassInCache (className);
724724
725725 if (global_class == nullptr ) {
726+ auto classIsMissing = CheckForClassMissingCache (className);
727+ // class is missing. Set the same JNI error we had when we tried to find it the first time
728+ if (classIsMissing != nullptr ) {
729+ m_env->Throw (classIsMissing);
730+ return nullptr ;
731+ }
726732 jclass tmp = m_env->FindClass (className.c_str ());
727733
728734 if (m_env->ExceptionCheck () == JNI_TRUE) {
729735 m_env->ExceptionClear ();
730- string cannonicalClassName = Util::ConvertFromJniToCanonicalName (className);
731- jstring s = m_env->NewStringUTF (cannonicalClassName.c_str ());
732- tmp = static_cast <jclass>(m_env->CallStaticObjectMethod (RUNTIME_CLASS,
733- GET_CACHED_CLASS_METHOD_ID, s));
734-
735- m_env->DeleteLocalRef (s);
736+ string cannonicalClassName = Util::ConvertFromJniToCanonicalName (className);
737+ jstring s = m_env->NewStringUTF (cannonicalClassName.c_str ());
738+ tmp = static_cast <jclass>(m_env->CallStaticObjectMethod (RUNTIME_CLASS,
739+ GET_CACHED_CLASS_METHOD_ID, s));
740+
741+ m_env->DeleteLocalRef (s);
742+ // we failed our static class check
743+ // if we continue, we will crash (C++ level)
744+ // so just return null and let the runtime deal with the NativeScriptException
745+ if (m_env->ExceptionCheck () == JNI_TRUE) {
746+ auto tmpException = m_env->ExceptionOccurred ();
747+ m_env->ExceptionClear ();
748+ m_env->Throw (InsertClassIntoMissingCache (className, tmpException));
749+ return nullptr ;
750+ }
736751 }
737752
738753 global_class = InsertClassIntoCache (className, tmp);
@@ -760,6 +775,25 @@ jclass JEnv::InsertClassIntoCache(const string &className, jclass &tmp) {
760775 return global_class;
761776}
762777
778+ jthrowable JEnv::CheckForClassMissingCache (const string &className) {
779+ jthrowable throwable = nullptr ;
780+ auto itFound = s_missingClasses.find (className);
781+
782+ if (itFound != s_missingClasses.end ()) {
783+ throwable = itFound->second ;
784+ }
785+
786+ return throwable;
787+ }
788+
789+ jthrowable JEnv::InsertClassIntoMissingCache (const string &className,const jthrowable &tmp) {
790+ auto throwable = reinterpret_cast <jthrowable>(m_env->NewGlobalRef (tmp));
791+ s_missingClasses.insert (make_pair (className, throwable));
792+ m_env->DeleteLocalRef (tmp);
793+
794+ return throwable;
795+ }
796+
763797jobject JEnv::NewDirectByteBuffer (void *address, jlong capacity) {
764798 jobject jo = m_env->NewDirectByteBuffer (address, capacity);
765799 CheckForJavaException ();
@@ -822,6 +856,7 @@ void JEnv::CheckForJavaException() {
822856
823857JavaVM *JEnv::s_jvm = nullptr ;
824858map<string, jclass> JEnv::s_classCache;
859+ map<string, jthrowable> JEnv::s_missingClasses;
825860jclass JEnv::RUNTIME_CLASS = nullptr ;
826861jmethodID JEnv::GET_CACHED_CLASS_METHOD_ID = nullptr ;
827862
0 commit comments