java-native-access/jna · critical · RuntimeException

UTF-16LE charset is not supported

Error message

UTF-16LE charset is not supported

What it means

WTypes.BSTR.setValue() encodes the Java string as UTF-16LE via String.getBytes("UTF-16LE"). Every compliant JVM must provide this charset, but if the encoding lookup throws UnsupportedEncodingException the library wraps it in this RuntimeException. It indicates a fundamentally broken JVM charset configuration rather than a data problem.

Solutions

  1. Use a standard, up-to-date JVM (Temurin/Oracle/Amazon Corretto) instead of a stripped custom runtime.
  2. Check for custom CharsetProvider implementations on the classpath and remove/fix them.
  3. Reinstall/verify the JDK/JRE installation.
  4. Catch the RuntimeException only as a last resort — it signals an unrecoverable environment problem.

Example fix

// before
BSTR bstr = new BSTR("value"); // throws on broken JVM
// after
if (Charset.isSupported("UTF-16LE")) {
    BSTR bstr = new BSTR("value");
} else {
    throw new IllegalStateException("JVM missing UTF-16LE charset");
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Charset.isSupported("UTF-16LE"))
    throw new IllegalStateException("JVM lacks UTF-16LE charset; use a standard JRE");

Type guard

static boolean utf16leSupported() {
    try { return Charset.forName("UTF-16LE") != null; }
    catch (Exception e) { return false; }
}

Try / catch

try {
    BSTR b = new BSTR(value);
} catch (RuntimeException e) {
    throw new IllegalStateException("Broken JVM charset environment", e);
}

Prevention

When it happens

Trigger: Constructing a BSTR (or calling setValue) on a JVM whose charset provider fails to resolve "UTF-16LE" — essentially only with a broken/exotic JRE, a faulty CharsetProvider, or a severely corrupted Java installation.

Common situations: Running on a stripped-down/custom JVM build lacking standard charsets; broken java.nio.charset.spi.CharsetProvider registration on the classpath; corrupted JRE runtime files.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/826ff9c18675bd9c. Report an issue: GitHub.

Appendix: source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/WTypes.java:148

        /**
         * @deprecated Users should not change the value of an allocated {@link BSTR}.
         */
        @Deprecated
        public void setValue(String value) {
            if(value == null) {
                value = "";
            }
            try {
                byte[] encodedValue = value.getBytes("UTF-16LE");
                // 4 bytes for the length prefix, length for the encoded data,
                // 2 bytes for the two NULL terminators
                Memory mem = new Memory(4 + encodedValue.length + 2);
                mem.clear();
                mem.setInt(0, encodedValue.length);
                mem.write(4, encodedValue, 0, encodedValue.length);
                this.setPointer(mem.share(4));
            } catch (UnsupportedEncodingException ex) {
                throw new RuntimeException("UTF-16LE charset is not supported", ex);
            }
        }

        public String getValue() {
            try {
                Pointer pointer = this.getPointer();
                if(pointer == null) {
                    return "";
                }
                int stringLength = pointer.getInt(-4);
                return new String(pointer.getByteArray(0, stringLength), "UTF-16LE");
            } catch (UnsupportedEncodingException ex) {
                throw new RuntimeException("UTF-16LE charset is not supported", ex);
            }
        }

        @Override
        public String toString() {

View on GitHub (pinned to d036ad9781)