I just saw a question on StackOverflow [1] which reports to have the same issue as in JDK-8226810 [2] - with the same stack trace.

While I could not reproduce the issue, I tried to understand which code path could lead to that outcome.
While doing so I did come across getEncodingInternal in java_props_md.c [3]

The path when GetLocaleInfo in line 72 fails just sets the codepage to 1252.
The following switch doesn't have a branch for codepage 1252, so the default branch is used.

The first two elements of the char array are set to "Cp", while the rest of that char array is still uninitialized.
This (partially) uninitialized array is then returned.

This seems wrong.
I would therefore either change codepage to 0 (resulting in a default encoding of UTF-8) or also copy the "Cp1252" to the char buffer.

----
(More when I follow this code path):
In InitializeEncoding [4] this invalid encoding is then set to jnuEncoding, and fastEncoding to NO_FAST_ENCODING. A call to JNU_NewStringPlatform will then result in a call to newSizedStringJava [5], where jnuEncodingSupported is called. This calls java.nio.charset.Charset.isSupported(jnuEncoding) and caches the result - I assume it returns false. Or throws.

This means new String(byte[]) is called.

Here comes the puzzler: java.lang.StringCoding.decode(byte[],int,int) calls Charset.getDefaultCharset() as first action. - and does not fall back to iso-8859-1 as the comment in newSizedStringJava suggests.

Charset.getDefaultCharset() then tries to read the properties - which are currently in the process to be initialized - and fails with a NullPointerException.

----

In the end, I don't know what causes the bug, or how I can replicate it.
I think I did find a likely suspect.

I therefore would like to propose the following patch:

diff --git a/src/java.base/windows/native/libjava/java_props_md.c b/src/java.base/windows/native/libjava/java_props_md.c
--- a/src/java.base/windows/native/libjava/java_props_md.c
+++ b/src/java.base/windows/native/libjava/java_props_md.c
@@ -73,6 +73,7 @@
                       LOCALE_IDEFAULTANSICODEPAGE,
                       ret+2, 14) == 0) {
         codepage = 1252;
+        strcpy(ret, "Cp1252");
     } else {
         codepage = atoi(ret+2);
     }

Because this path is not taken on my system, I can't test if this change affects anything. Tests run as before.
But I still think that it is The Right Thing To Do.

Maybe logging the GetLastError too - but it's very early in the VM's startup. I did consider calling GetLocaleInfo twice - with NULL as buffer and 0 as length - which returns the required size of the buffer.
But that would have some implication on the startup time.
I could also check GetLastError and try again with a bigger buffer - but then the question arises: Can the VM handle such a charset?

Johannes

[1]: https://stackoverflow.com/questions/61650372/jdk-14-0-1-error-occurred-during-initialization-of-vm-java-lang-nullpointerexcep
[2]: https://bugs.openjdk.java.net/browse/JDK-8226810
[3]: https://hg.openjdk.java.net/jdk/jdk/file/d40d865753fb/src/java.base/windows/native/libjava/java_props_md.c#l64 [4]: https://hg.openjdk.java.net/jdk/jdk/file/d40d865753fb/src/java.base/share/native/libjava/jni_util.c#l773 [5]: https://hg.openjdk.java.net/jdk/jdk/file/d40d865753fb/src/java.base/share/native/libjava/jni_util.c#l661

Reply via email to