Skip to content

Commit 20b1d19

Browse files
Peter Hofernaotoj
Peter Hofer
authored andcommitted
8305746: InitializeEncoding should cache Charset object instead of charset name
Reviewed-by: naoto
1 parent 955abca commit 20b1d19

File tree

1 file changed

+37
-33
lines changed

1 file changed

+37
-33
lines changed

src/java.base/share/native/libjava/jni_util.c

+37-33
Original file line numberDiff line numberDiff line change
@@ -630,11 +630,11 @@ getStringCp1252Chars(JNIEnv *env, jstring jstr)
630630
}
631631

632632
static int fastEncoding = NO_ENCODING_YET;
633-
static jstring jnuEncoding = NULL;
633+
static jobject jnuCharset = NULL;
634634

635635
/* Cached method IDs */
636-
static jmethodID String_init_ID; /* String(byte[], enc) */
637-
static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
636+
static jmethodID String_init_ID; /* String(byte[], Charset) */
637+
static jmethodID String_getBytes_ID; /* String.getBytes(Charset) */
638638

639639
/* Cached field IDs */
640640
static jfieldID String_coder_ID; /* String.coder */
@@ -658,7 +658,7 @@ newSizedStringJava(JNIEnv *env, const char *str, const int len)
658658
CHECK_NULL_RETURN(strClazz, 0);
659659
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
660660
result = (*env)->NewObject(env, strClazz,
661-
String_init_ID, bytes, jnuEncoding);
661+
String_init_ID, bytes, jnuCharset);
662662
(*env)->DeleteLocalRef(env, bytes);
663663
return result;
664664
}
@@ -717,18 +717,15 @@ InitializeEncoding(JNIEnv *env, const char *encname)
717717
* "en_GB" locale -> "ISO8859-1" (on Sol 7/8)
718718
* "en_UK" locale -> "ISO8859-1" (on 2.6)
719719
*/
720+
const char *charsetname = NULL;
720721
if ((strcmp(encname, "8859_1") == 0) ||
721722
(strcmp(encname, "ISO8859-1") == 0) ||
722723
(strcmp(encname, "ISO8859_1") == 0) ||
723724
(strcmp(encname, "ISO-8859-1") == 0)) {
724725
fastEncoding = FAST_8859_1;
725726
} else if (strcmp(encname, "UTF-8") == 0) {
726-
jstring enc = (*env)->NewStringUTF(env, encname);
727-
if (enc == NULL)
728-
return;
727+
charsetname = encname;
729728
fastEncoding = FAST_UTF_8;
730-
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
731-
(*env)->DeleteLocalRef(env, enc);
732729
} else if (strcmp(encname, "ISO646-US") == 0) {
733730
fastEncoding = FAST_646_US;
734731
} else if (strcmp(encname, "Cp1252") == 0 ||
@@ -738,31 +735,38 @@ InitializeEncoding(JNIEnv *env, const char *encname)
738735
strcmp(encname, "utf-16le") == 0) {
739736
fastEncoding = FAST_CP1252;
740737
} else {
741-
jboolean exe;
742-
jstring enc = (*env)->NewStringUTF(env, encname);
743-
if (enc == NULL)
738+
charsetname = encname;
739+
fastEncoding = NO_FAST_ENCODING;
740+
}
741+
while (charsetname != NULL) {
742+
jstring enc = (*env)->NewStringUTF(env, charsetname);
743+
if (enc == NULL) {
744+
fastEncoding = NO_ENCODING_YET;
744745
return;
746+
}
747+
jboolean exc;
748+
jvalue charset = JNU_CallStaticMethodByName(
749+
env, &exc,
750+
"java/nio/charset/Charset",
751+
"forName",
752+
"(Ljava/lang/String;)Ljava/nio/charset/Charset;",
753+
enc);
754+
if (exc) {
755+
(*env)->ExceptionClear(env);
756+
}
757+
(*env)->DeleteLocalRef(env, enc);
745758

746-
if ((jboolean) JNU_CallStaticMethodByName (
747-
env, &exe,
748-
"java/nio/charset/Charset",
749-
"isSupported",
750-
"(Ljava/lang/String;)Z",
751-
enc).z == JNI_TRUE) {
752-
fastEncoding = NO_FAST_ENCODING;
753-
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
754-
} else {
755-
// jnuEncoding falls back to UTF-8
756-
jstring utf8 = (*env)->NewStringUTF(env, "UTF-8");
757-
if (utf8 == NULL) {
758-
(*env)->DeleteLocalRef(env, enc);
759-
return;
760-
}
759+
if (!exc && charset.l != NULL) {
760+
jnuCharset = (*env)->NewGlobalRef(env, charset.l);
761+
(*env)->DeleteLocalRef(env, charset.l);
762+
break; // success, continue below
763+
} else if (strcmp(charsetname, "UTF-8") != 0) { // fall back
764+
charsetname = "UTF-8";
761765
fastEncoding = FAST_UTF_8;
762-
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, utf8);
763-
(*env)->DeleteLocalRef(env, utf8);
766+
} else { // give up
767+
fastEncoding = NO_ENCODING_YET;
768+
return;
764769
}
765-
(*env)->DeleteLocalRef(env, enc);
766770
}
767771
} else {
768772
JNU_ThrowInternalError(env, "platform encoding undefined");
@@ -771,10 +775,10 @@ InitializeEncoding(JNIEnv *env, const char *encname)
771775

772776
/* Initialize method-id cache */
773777
String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
774-
"getBytes", "(Ljava/lang/String;)[B");
778+
"getBytes", "(Ljava/nio/charset/Charset;)[B");
775779
CHECK_NULL(String_getBytes_ID);
776780
String_init_ID = (*env)->GetMethodID(env, strClazz,
777-
"<init>", "([BLjava/lang/String;)V");
781+
"<init>", "([BLjava/nio/charset/Charset;)V");
778782
CHECK_NULL(String_init_ID);
779783
String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
780784
CHECK_NULL(String_coder_ID);
@@ -813,7 +817,7 @@ static const char* getStringBytes(JNIEnv *env, jstring jstr) {
813817
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
814818
return 0;
815819

816-
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
820+
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuCharset);
817821
if (hab != 0) {
818822
if (!(*env)->ExceptionCheck(env)) {
819823
jint len = (*env)->GetArrayLength(env, hab);

0 commit comments

Comments
 (0)