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;