--- old/src/share/vm/prims/jni.cpp 2015-10-30 19:14:57.044475816 +0100 +++ new/src/share/vm/prims/jni.cpp 2015-10-30 19:14:56.972475814 +0100 @@ -2474,12 +2474,18 @@ typeArrayOop s_value = java_lang_String::value(s); if (s_value != NULL) { int s_len = java_lang_String::length(s); - int s_offset = java_lang_String::offset(s); + bool is_latin1 = java_lang_String::is_latin1(s); 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); + if (!is_latin1) { + memcpy(buf, s_value->char_at_addr(0), sizeof(jchar)*s_len); + } else { + for (int i = 0; i < s_len; i++) { + buf[i] = ((jchar) s_value->byte_at(i)) & 0xff; + } + } } buf[s_len] = 0; //%note jni_5 @@ -3118,9 +3124,15 @@ THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); } else { if (len > 0) { - int s_offset = java_lang_String::offset(s); typeArrayOop s_value = java_lang_String::value(s); - memcpy(buf, s_value->char_at_addr(s_offset+start), sizeof(jchar)*len); + bool is_latin1 = java_lang_String::is_latin1(s); + if (!is_latin1) { + memcpy(buf, s_value->char_at_addr(start), sizeof(jchar)*len); + } else { + for (int i = 0; i < len; i++) { + buf[i] = ((jchar) s_value->byte_at(i + start)) & 0xff; + } + } } } JNI_END @@ -3186,18 +3198,23 @@ JNIWrapper("GetStringCritical"); HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy); GC_locker::lock_critical(thread); - if (isCopy != NULL) { - *isCopy = JNI_FALSE; - } 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); + bool is_latin1 = java_lang_String::is_latin1(s); + if (isCopy != NULL) { + *isCopy = is_latin1 ? JNI_TRUE : JNI_FALSE; + } const jchar* ret; - if (s_len > 0) { - ret = s_value->char_at_addr(s_offset); + if (!is_latin1) { + ret = s_value->char_at_addr(0); } else { - ret = (jchar*) s_value->base(T_CHAR); + // Inflate latin1 encoded string to UTF16 + int s_len = java_lang_String::length(s); + jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len, mtInternal); + for (int i = 0; i < s_len; i++) { + buf[i] = ((jchar) s_value->byte_at(i)) & 0xff; + } + ret = &buf[0]; } HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN((uint16_t *) ret); return ret; @@ -3207,7 +3224,14 @@ JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars)) JNIWrapper("ReleaseStringCritical"); HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(env, str, (uint16_t *) chars); - // The str and chars arguments are ignored + // The str and chars arguments are ignored for UTF16 strings + oop s = JNIHandles::resolve_non_null(str); + bool is_latin1 = java_lang_String::is_latin1(s); + if (is_latin1) { + // For latin1 string, free jchar array allocated by earlier call to GetStringCritical. + // This assumes that ReleaseStringCritical bookends GetStringCritical. + FREE_C_HEAP_ARRAY(jchar, chars); + } GC_locker::unlock_critical(thread); HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN(); JNI_END