8305746: InitializeEncoding should cache Charset object instead of charset name

Reviewed-by: naoto
This commit is contained in:
Peter Hofer 2023-04-20 16:11:29 +00:00 committed by Naoto Sato
parent 955abcae55
commit 20b1d19d26

@ -630,11 +630,11 @@ getStringCp1252Chars(JNIEnv *env, jstring jstr)
}
static int fastEncoding = NO_ENCODING_YET;
static jstring jnuEncoding = NULL;
static jobject jnuCharset = NULL;
/* Cached method IDs */
static jmethodID String_init_ID; /* String(byte[], enc) */
static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
static jmethodID String_init_ID; /* String(byte[], Charset) */
static jmethodID String_getBytes_ID; /* String.getBytes(Charset) */
/* Cached field IDs */
static jfieldID String_coder_ID; /* String.coder */
@ -658,7 +658,7 @@ newSizedStringJava(JNIEnv *env, const char *str, const int len)
CHECK_NULL_RETURN(strClazz, 0);
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
result = (*env)->NewObject(env, strClazz,
String_init_ID, bytes, jnuEncoding);
String_init_ID, bytes, jnuCharset);
(*env)->DeleteLocalRef(env, bytes);
return result;
}
@ -717,18 +717,15 @@ InitializeEncoding(JNIEnv *env, const char *encname)
* "en_GB" locale -> "ISO8859-1" (on Sol 7/8)
* "en_UK" locale -> "ISO8859-1" (on 2.6)
*/
const char *charsetname = NULL;
if ((strcmp(encname, "8859_1") == 0) ||
(strcmp(encname, "ISO8859-1") == 0) ||
(strcmp(encname, "ISO8859_1") == 0) ||
(strcmp(encname, "ISO-8859-1") == 0)) {
fastEncoding = FAST_8859_1;
} else if (strcmp(encname, "UTF-8") == 0) {
jstring enc = (*env)->NewStringUTF(env, encname);
if (enc == NULL)
return;
charsetname = encname;
fastEncoding = FAST_UTF_8;
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
(*env)->DeleteLocalRef(env, enc);
} else if (strcmp(encname, "ISO646-US") == 0) {
fastEncoding = FAST_646_US;
} else if (strcmp(encname, "Cp1252") == 0 ||
@ -738,31 +735,38 @@ InitializeEncoding(JNIEnv *env, const char *encname)
strcmp(encname, "utf-16le") == 0) {
fastEncoding = FAST_CP1252;
} else {
jboolean exe;
jstring enc = (*env)->NewStringUTF(env, encname);
if (enc == NULL)
charsetname = encname;
fastEncoding = NO_FAST_ENCODING;
}
while (charsetname != NULL) {
jstring enc = (*env)->NewStringUTF(env, charsetname);
if (enc == NULL) {
fastEncoding = NO_ENCODING_YET;
return;
if ((jboolean) JNU_CallStaticMethodByName (
env, &exe,
"java/nio/charset/Charset",
"isSupported",
"(Ljava/lang/String;)Z",
enc).z == JNI_TRUE) {
fastEncoding = NO_FAST_ENCODING;
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
} else {
// jnuEncoding falls back to UTF-8
jstring utf8 = (*env)->NewStringUTF(env, "UTF-8");
if (utf8 == NULL) {
(*env)->DeleteLocalRef(env, enc);
return;
}
fastEncoding = FAST_UTF_8;
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, utf8);
(*env)->DeleteLocalRef(env, utf8);
}
jboolean exc;
jvalue charset = JNU_CallStaticMethodByName(
env, &exc,
"java/nio/charset/Charset",
"forName",
"(Ljava/lang/String;)Ljava/nio/charset/Charset;",
enc);
if (exc) {
(*env)->ExceptionClear(env);
}
(*env)->DeleteLocalRef(env, enc);
if (!exc && charset.l != NULL) {
jnuCharset = (*env)->NewGlobalRef(env, charset.l);
(*env)->DeleteLocalRef(env, charset.l);
break; // success, continue below
} else if (strcmp(charsetname, "UTF-8") != 0) { // fall back
charsetname = "UTF-8";
fastEncoding = FAST_UTF_8;
} else { // give up
fastEncoding = NO_ENCODING_YET;
return;
}
}
} else {
JNU_ThrowInternalError(env, "platform encoding undefined");
@ -771,10 +775,10 @@ InitializeEncoding(JNIEnv *env, const char *encname)
/* Initialize method-id cache */
String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
"getBytes", "(Ljava/lang/String;)[B");
"getBytes", "(Ljava/nio/charset/Charset;)[B");
CHECK_NULL(String_getBytes_ID);
String_init_ID = (*env)->GetMethodID(env, strClazz,
"<init>", "([BLjava/lang/String;)V");
"<init>", "([BLjava/nio/charset/Charset;)V");
CHECK_NULL(String_init_ID);
String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
CHECK_NULL(String_coder_ID);
@ -813,7 +817,7 @@ static const char* getStringBytes(JNIEnv *env, jstring jstr) {
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
return 0;
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuCharset);
if (hab != 0) {
if (!(*env)->ExceptionCheck(env)) {
jint len = (*env)->GetArrayLength(env, hab);