Prevent local reference table overflows

If we're grabbing references to many strings in a loop, we have to
remove our local references so we don't overflow the VM's local
reference table.

Also, use env->ExceptionCheck() instead of checking for NULL value
returns on trying to allocate new items.

Bug: 2663816
Change-Id: I9cb5e17f6181dbb2f2c03d53841b2f5d8ab10f68
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index a2b7cc4..b7d0c67 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1504,8 +1504,7 @@
     }
 
     jobjectArray array = env->NewObjectArray(N, cls, NULL);
-    if (array == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
+    if (env->ExceptionCheck()) {
         res.unlockBag(startOfBag);
         return NULL;
     }
@@ -1533,15 +1532,23 @@
             } else {
                 const char16_t* str16 = pool->stringAt(value.data, &strLen);
                 str = env->NewString(str16, strLen);
-                if (str == NULL) {
-                    doThrow(env, "java/lang/OutOfMemoryError");
-                    res.unlockBag(startOfBag);
-                    return NULL;
-                }
+            }
+
+            // If one of our NewString{UTF} calls failed due to memory, an
+            // exception will be pending.
+            if (env->ExceptionCheck()) {
+                res.unlockBag(startOfBag);
+                return NULL;
             }
         }
 
         env->SetObjectArrayElement(array, i, str);
+
+        // If we have a large amount of strings in our array, we might
+        // overflow the local reference table of the VM.
+        if (str != NULL) {
+            env->DeleteLocalRef(str);
+        }
     }
     res.unlockBag(startOfBag);
     return array;