# HG changeset patch # User dsimms # Date 1377502381 -7200 # Node ID 409c50cf1e5de3347da794f49c25058f695b6ace # Parent 8f3ad1962aefc84e2d9c9957fdf4068c369e5db6 8022683: JNI GetStringUTFChars should return NULL on allocation failure not abort the VM Summary: Return NULL on OOM from GetStringChars, GetStringUTFChars and GetArrayElements family of functions. Reviewed-by: dholmes, coleenp diff -r 8f3ad1962aef -r 409c50cf1e5d hotspot/src/share/vm/memory/allocation.hpp --- 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) diff -r 8f3ad1962aef -r 409c50cf1e5d hotspot/src/share/vm/prims/jni.cpp --- 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