8022683: JNI GetStringUTFChars should return NULL on allocation failure not abort the VM
Summary: Return NULL on OOM from GetStringChars, GetStringUTFChars and Get<PrimitiveType>ArrayElements family of functions.
Reviewed-by: dholmes, coleenp
--- a/hotspot/src/share/vm/memory/allocation.hpp Sun Aug 25 21:21:18 2013 -0400
+++ b/hotspot/src/share/vm/memory/allocation.hpp Mon Aug 26 09:33:01 2013 +0200
@@ -666,7 +666,7 @@
NEW_RESOURCE_ARRAY_RETURN_NULL(type, 1)
#define NEW_C_HEAP_ARRAY3(type, size, memflags, pc, allocfail)\
- (type*) AllocateHeap(size * sizeof(type), memflags, pc, allocfail)
+ (type*) AllocateHeap((size) * sizeof(type), memflags, pc, allocfail)
#define NEW_C_HEAP_ARRAY2(type, size, memflags, pc)\
(type*) (AllocateHeap((size) * sizeof(type), memflags, pc))
@@ -675,16 +675,16 @@
(type*) (AllocateHeap((size) * sizeof(type), memflags))
#define NEW_C_HEAP_ARRAY2_RETURN_NULL(type, size, memflags, pc)\
- NEW_C_HEAP_ARRAY3(type, size, memflags, pc, AllocFailStrategy::RETURN_NULL)
+ NEW_C_HEAP_ARRAY3(type, (size), memflags, pc, AllocFailStrategy::RETURN_NULL)
#define NEW_C_HEAP_ARRAY_RETURN_NULL(type, size, memflags)\
- NEW_C_HEAP_ARRAY3(type, size, memflags, (address)0, AllocFailStrategy::RETURN_NULL)
+ NEW_C_HEAP_ARRAY3(type, (size), memflags, (address)0, AllocFailStrategy::RETURN_NULL)
#define REALLOC_C_HEAP_ARRAY(type, old, size, memflags)\
- (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), memflags))
+ (type*) (ReallocateHeap((char*)(old), (size) * sizeof(type), memflags))
#define REALLOC_C_HEAP_ARRAY_RETURN_NULL(type, old, size, memflags)\
- (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), memflags, AllocFailStrategy::RETURN_NULL))
+ (type*) (ReallocateHeap((char*)(old), (size) * sizeof(type), memflags, AllocFailStrategy::RETURN_NULL))
#define FREE_C_HEAP_ARRAY(type, old, memflags) \
FreeHeap((char*)(old), memflags)
--- a/hotspot/src/share/vm/prims/jni.cpp Sun Aug 25 21:21:18 2013 -0400
+++ b/hotspot/src/share/vm/prims/jni.cpp Mon Aug 26 09:33:01 2013 +0200
@@ -3234,19 +3234,22 @@
HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(
env, string, (uintptr_t *) isCopy);
#endif /* USDT2 */
- //%note jni_5
- if (isCopy != NULL) {
- *isCopy = JNI_TRUE;
- }
oop s = JNIHandles::resolve_non_null(string);
int s_len = java_lang_String::length(s);
typeArrayOop s_value = java_lang_String::value(s);
int s_offset = java_lang_String::offset(s);
- jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len + 1, mtInternal); // add one for zero termination
- if (s_len > 0) {
- memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);
+ jchar* buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
+ /* JNI Specification states return NULL on OOM */
+ if (buf != NULL) {
+ if (s_len > 0) {
+ memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);
+ }
+ buf[s_len] = 0;
+ //%note jni_5
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
}
- buf[s_len] = 0;
#ifndef USDT2
DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf);
#else /* USDT2 */
@@ -3335,9 +3338,14 @@
#endif /* USDT2 */
oop java_string = JNIHandles::resolve_non_null(string);
size_t length = java_lang_String::utf8_length(java_string);
- char* result = AllocateHeap(length + 1, mtInternal);
- java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
- if (isCopy != NULL) *isCopy = JNI_TRUE;
+ /* JNI Specification states return NULL on OOM */
+ char* result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
+ if (result != NULL) {
+ java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
+ }
#ifndef USDT2
DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);
#else /* USDT2 */
@@ -3591,11 +3599,16 @@
* Avoid asserts in typeArrayOop. */ \
result = (ElementType*)get_bad_address(); \
} else { \
- result = NEW_C_HEAP_ARRAY(ElementType, len, mtInternal); \
- /* copy the array to the c chunk */ \
- memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
+ /* JNI Specification states return NULL on OOM */ \
+ result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \
+ if (result != NULL) { \
+ /* copy the array to the c chunk */ \
+ memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
+ if (isCopy) { \
+ *isCopy = JNI_TRUE; \
+ } \
+ } \
} \
- if (isCopy) *isCopy = JNI_TRUE; \
DTRACE_PROBE1(hotspot_jni, Get##Result##ArrayElements__return, result);\
return result; \
JNI_END
@@ -3628,11 +3641,16 @@
* Avoid asserts in typeArrayOop. */ \
result = (ElementType*)get_bad_address(); \
} else { \
- result = NEW_C_HEAP_ARRAY(ElementType, len, mtInternal); \
- /* copy the array to the c chunk */ \
- memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
+ /* JNI Specification states return NULL on OOM */ \
+ result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \
+ if (result != NULL) { \
+ /* copy the array to the c chunk */ \
+ memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
+ if (isCopy) { \
+ *isCopy = JNI_TRUE; \
+ } \
+ } \
} \
- if (isCopy) *isCopy = JNI_TRUE; \
ReturnProbe; \
return result; \
JNI_END