mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8275007: Java fails to start with null charset if LC_ALL is set to certain locales
Reviewed-by: rriggs, iris, joehw, alanb
This commit is contained in:
parent
231fb61aae
commit
b8453ebdb4
2 changed files with 61 additions and 63 deletions
|
@ -33,7 +33,6 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
|
@ -45,9 +44,9 @@ import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.CharacterCodingException;
|
|
||||||
import java.nio.channels.Channel;
|
import java.nio.channels.Channel;
|
||||||
import java.nio.channels.spi.SelectorProvider;
|
import java.nio.channels.spi.SelectorProvider;
|
||||||
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.AccessControlContext;
|
import java.security.AccessControlContext;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
|
@ -84,6 +83,7 @@ import jdk.internal.vm.annotation.Stable;
|
||||||
import sun.nio.fs.DefaultFileSystemProvider;
|
import sun.nio.fs.DefaultFileSystemProvider;
|
||||||
import sun.reflect.annotation.AnnotationType;
|
import sun.reflect.annotation.AnnotationType;
|
||||||
import sun.nio.ch.Interruptible;
|
import sun.nio.ch.Interruptible;
|
||||||
|
import sun.nio.cs.UTF_8;
|
||||||
import sun.security.util.SecurityConstants;
|
import sun.security.util.SecurityConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,6 +188,11 @@ public final class System {
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
private static volatile SecurityManager security; // read by VM
|
private static volatile SecurityManager security; // read by VM
|
||||||
|
|
||||||
|
// `sun.jnu.encoding` if it is not supported. Otherwise null.
|
||||||
|
// It is initialized in `initPhase1()` before any charset providers
|
||||||
|
// are initialized.
|
||||||
|
private static String notSupportedJnuEncoding;
|
||||||
|
|
||||||
// return true if a security manager is allowed
|
// return true if a security manager is allowed
|
||||||
private static boolean allowSecurityManager() {
|
private static boolean allowSecurityManager() {
|
||||||
return (allowSecurityManager != NEVER);
|
return (allowSecurityManager != NEVER);
|
||||||
|
@ -2017,10 +2022,9 @@ public final class System {
|
||||||
* Create PrintStream for stdout/err based on encoding.
|
* Create PrintStream for stdout/err based on encoding.
|
||||||
*/
|
*/
|
||||||
private static PrintStream newPrintStream(FileOutputStream fos, String enc) {
|
private static PrintStream newPrintStream(FileOutputStream fos, String enc) {
|
||||||
if (enc != null) {
|
if (enc != null) {
|
||||||
try {
|
return new PrintStream(new BufferedOutputStream(fos, 128), true,
|
||||||
return new PrintStream(new BufferedOutputStream(fos, 128), true, enc);
|
Charset.forName(enc, UTF_8.INSTANCE));
|
||||||
} catch (UnsupportedEncodingException uee) {}
|
|
||||||
}
|
}
|
||||||
return new PrintStream(new BufferedOutputStream(fos, 128), true);
|
return new PrintStream(new BufferedOutputStream(fos, 128), true);
|
||||||
}
|
}
|
||||||
|
@ -2113,6 +2117,13 @@ public final class System {
|
||||||
VM.saveProperties(tempProps);
|
VM.saveProperties(tempProps);
|
||||||
props = createProperties(tempProps);
|
props = createProperties(tempProps);
|
||||||
|
|
||||||
|
// Check if sun.jnu.encoding is supported. If not, replace it with UTF-8.
|
||||||
|
var jnuEncoding = props.getProperty("sun.jnu.encoding");
|
||||||
|
if (jnuEncoding == null || !Charset.isSupported(jnuEncoding)) {
|
||||||
|
notSupportedJnuEncoding = jnuEncoding == null ? "null" : jnuEncoding;
|
||||||
|
props.setProperty("sun.jnu.encoding", "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
StaticProperty.javaHome(); // Load StaticProperty to cache the property values
|
StaticProperty.javaHome(); // Load StaticProperty to cache the property values
|
||||||
|
|
||||||
lineSeparator = props.getProperty("line.separator");
|
lineSeparator = props.getProperty("line.separator");
|
||||||
|
@ -2141,7 +2152,6 @@ public final class System {
|
||||||
Thread current = Thread.currentThread();
|
Thread current = Thread.currentThread();
|
||||||
current.getThreadGroup().add(current);
|
current.getThreadGroup().add(current);
|
||||||
|
|
||||||
|
|
||||||
// Subsystems that are invoked during initialization can invoke
|
// Subsystems that are invoked during initialization can invoke
|
||||||
// VM.isBooted() in order to avoid doing things that should
|
// VM.isBooted() in order to avoid doing things that should
|
||||||
// wait until the VM is fully initialized. The initialization level
|
// wait until the VM is fully initialized. The initialization level
|
||||||
|
@ -2248,6 +2258,14 @@ public final class System {
|
||||||
WARNING: The Security Manager is deprecated and will be removed in a future release""");
|
WARNING: The Security Manager is deprecated and will be removed in a future release""");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit a warning if `sun.jnu.encoding` is not supported.
|
||||||
|
if (notSupportedJnuEncoding != null) {
|
||||||
|
System.err.println(
|
||||||
|
"WARNING: The encoding of the underlying platform's" +
|
||||||
|
" file system is not supported: " +
|
||||||
|
notSupportedJnuEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
initialErrStream = System.err;
|
initialErrStream = System.err;
|
||||||
|
|
||||||
// initializing the system class loader
|
// initializing the system class loader
|
||||||
|
|
|
@ -639,21 +639,6 @@ static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
|
||||||
static jfieldID String_coder_ID; /* String.coder */
|
static jfieldID String_coder_ID; /* String.coder */
|
||||||
static jfieldID String_value_ID; /* String.value */
|
static jfieldID String_value_ID; /* String.value */
|
||||||
|
|
||||||
static jboolean isJNUEncodingSupported = JNI_FALSE;
|
|
||||||
static jboolean jnuEncodingSupported(JNIEnv *env) {
|
|
||||||
jboolean exe;
|
|
||||||
if (isJNUEncodingSupported == JNI_TRUE) {
|
|
||||||
return JNI_TRUE;
|
|
||||||
}
|
|
||||||
isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
|
|
||||||
env, &exe,
|
|
||||||
"java/nio/charset/Charset",
|
|
||||||
"isSupported",
|
|
||||||
"(Ljava/lang/String;)Z",
|
|
||||||
jnuEncoding).z;
|
|
||||||
return isJNUEncodingSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a new string by converting str to a heap-allocated byte array and
|
/* Create a new string by converting str to a heap-allocated byte array and
|
||||||
* calling the appropriate String constructor.
|
* calling the appropriate String constructor.
|
||||||
*/
|
*/
|
||||||
|
@ -671,22 +656,8 @@ newSizedStringJava(JNIEnv *env, const char *str, const int len)
|
||||||
jclass strClazz = JNU_ClassString(env);
|
jclass strClazz = JNU_ClassString(env);
|
||||||
CHECK_NULL_RETURN(strClazz, 0);
|
CHECK_NULL_RETURN(strClazz, 0);
|
||||||
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
|
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
|
||||||
if (jnuEncodingSupported(env)) {
|
result = (*env)->NewObject(env, strClazz,
|
||||||
result = (*env)->NewObject(env, strClazz,
|
String_init_ID, bytes, jnuEncoding);
|
||||||
String_init_ID, bytes, jnuEncoding);
|
|
||||||
} else {
|
|
||||||
/*If the encoding specified in sun.jnu.encoding is not endorsed
|
|
||||||
by "Charset.isSupported" we have to fall back to use String(byte[])
|
|
||||||
explicitly here without specifying the encoding name, in which the
|
|
||||||
StringCoding class will pickup the iso-8859-1 as the fallback
|
|
||||||
converter for us.
|
|
||||||
*/
|
|
||||||
jmethodID mid = (*env)->GetMethodID(env, strClazz,
|
|
||||||
"<init>", "([B)V");
|
|
||||||
if (mid != NULL) {
|
|
||||||
result = (*env)->NewObject(env, strClazz, mid, bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*env)->DeleteLocalRef(env, bytes);
|
(*env)->DeleteLocalRef(env, bytes);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -766,11 +737,30 @@ InitializeEncoding(JNIEnv *env, const char *encname)
|
||||||
strcmp(encname, "utf-16le") == 0) {
|
strcmp(encname, "utf-16le") == 0) {
|
||||||
fastEncoding = FAST_CP1252;
|
fastEncoding = FAST_CP1252;
|
||||||
} else {
|
} else {
|
||||||
|
jboolean exe;
|
||||||
jstring enc = (*env)->NewStringUTF(env, encname);
|
jstring enc = (*env)->NewStringUTF(env, encname);
|
||||||
if (enc == NULL)
|
if (enc == NULL)
|
||||||
return;
|
return;
|
||||||
fastEncoding = NO_FAST_ENCODING;
|
|
||||||
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
|
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);
|
||||||
|
}
|
||||||
(*env)->DeleteLocalRef(env, enc);
|
(*env)->DeleteLocalRef(env, enc);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -822,32 +812,22 @@ static const char* getStringBytes(JNIEnv *env, jstring jstr) {
|
||||||
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
|
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (jnuEncodingSupported(env)) {
|
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
|
||||||
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
|
if (hab != 0) {
|
||||||
} else {
|
if (!(*env)->ExceptionCheck(env)) {
|
||||||
jmethodID mid;
|
jint len = (*env)->GetArrayLength(env, hab);
|
||||||
jclass strClazz = JNU_ClassString(env);
|
result = MALLOC_MIN4(len);
|
||||||
CHECK_NULL_RETURN(strClazz, 0);
|
if (result == 0) {
|
||||||
mid = (*env)->GetMethodID(env, strClazz,
|
JNU_ThrowOutOfMemoryError(env, 0);
|
||||||
"getBytes", "()[B");
|
(*env)->DeleteLocalRef(env, hab);
|
||||||
if (mid != NULL) {
|
return 0;
|
||||||
hab = (*env)->CallObjectMethod(env, jstr, mid);
|
}
|
||||||
|
(*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
|
||||||
|
result[len] = 0; /* NULL-terminate */
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!(*env)->ExceptionCheck(env)) {
|
(*env)->DeleteLocalRef(env, hab);
|
||||||
jint len = (*env)->GetArrayLength(env, hab);
|
|
||||||
result = MALLOC_MIN4(len);
|
|
||||||
if (result == 0) {
|
|
||||||
JNU_ThrowOutOfMemoryError(env, 0);
|
|
||||||
(*env)->DeleteLocalRef(env, hab);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
(*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
|
|
||||||
result[len] = 0; /* NULL-terminate */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(*env)->DeleteLocalRef(env, hab);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue