Java Platform Encoding

This came up at $WORK recently. We had a java program that was given input through command line arguments. Unfortunately, it went wrong when being passed UTF-8 characters (U+00A9 COPYRIGHT SIGN [©]). Printing out the command line arguments from inside Java showed that we had double encoded Unicode.

Initially, we just slapped -Dfile.encoding=UTF-8 on the command line. But that failed when the site that called this code went through an automatic restart. So we investigated the issue further.

We quickly found that the presence of absence of the LANG environment variable had a bearing on the matter.

NB: ShowSystemProperties.jar is very simple and just lists all system properties in sorted order.

$ java -version
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)
$ echo $LANG
$ java -jar ShowSystemProperties.jar | grep encoding
$ LANG= java -jar ShowSystemProperties.jar | grep encoding

So, setting file.encoding works, but there’s an internal property, sun.jnu.encoding as well.

Next, see what happens when we add the explicit override.

$ LANG= java -Dfile.encoding=UTF-8 -jar ShowSystemProperties.jar | grep encoding

Hey! sun.jnu.encoding isn’t changing!

Now, as far as I can see, sun.jnu.encoding isn’t actually documented anywhere. So you have to go into the source code for Java (openjdk’s jdk6-b16 in this case) to figure out what’s up.

Let’s start in main(), which is in java.c. Actually, it’s JavaMain() that we’re really interested in. In there you can see:

JavaMain(void * _args)
  jobjectArray mainArgs;
  /* Build argument array */
  mainArgs = NewPlatformStringArray(env, argv, argc);
  if (mainArgs == NULL) {
      goto leave;

NewPlatformStringArray() is defined in java.c and calls NewPlatformString() repeatedly with each command line argument. In turn, that calls new String(byte[], encoding). It gets the encoding from getPlatformEncoding(). That essentially calls System.getProperty("sun.jnu.encoding").

So where does that property get set? If you look in System.c, Java_java_lang_System_initProperties() calls:

    PUTPROP(props, "sun.jnu.encoding", sprops->sun_jnu_encoding);

sprops appears to get set in GetJavaProperties() in java_props_md.c. This interprets various environment variables including the one that control the locale. It appears to pull out everything after the period in the LANG environment variable as the encoding in order to get sun_jnu_encoding.

Phew. So we now know that there is a special property which gets used for interpreting “platform” strings like:

* Command line arguments
* Main class name
* Environment variables

And it can be overridden:

$ LANG= java -Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8 -jar ShowSystemProperties.jar | grep encoding

Comments 4

  1. Jayesh Malondkar wrote:

    The above article was a life-saver for me. We were stuck in an issue where we were not able to set Encoding of the JVM inspite of overridding the LANG variable.
    Thus, overridding the sun.jnu.encoding variable was the last resort. However, as rightly pointed out in the above artice, this variable is not well documented in the Java Documentation.

    The fine research and detail explanation given by : Dominic Mitchell ; made my day.
    Thanks a lot once again and keep up the good work.!!

    Posted 19 May 2011 at 03:20
  2. John Dell'Aera wrote:

    I have a java server app that creates UTF-8 file system names.
    Unfortunately, when I look at the file names the non-ascii characters of the file names are displayed with ‘?’. How do I get the system to display the appropriate UTF-8 character?

    System specs:
    Linux CentOS 6.0 #1 SMP Thu May 13 11:11:51 PDT 2010 x86_64 x86_64 x86_64 GNU/Linux

    Tomcat 6
    Java 1.6



    I even execute the following at startup:
    System.setProperty(“file.encoding”, “UTF-8”);
    System.setProperty(“encoding”, “UTF-8”);
    System.setProperty(“user.language”, “en_US.UTF-8”);
    System.setProperty(“”, “en_US.UTF-8”);
    System.setProperty(“sun.jnu.encoding”, “UTF8”);

    And where I create the file:
    fullPathName = new String(fullPathName.getBytes(“UTF-8”));
    InputStream is = file.getInputStream();
    input = new BufferedInputStream(is, STREAM_BUFFER_SIZE);
    output = new BufferedOutputStream(new FileOutputStream(fullPathName),

    // Read file from memory and write it to disk.
    int r;
    byte[] buf = new byte[STREAM_BUFFER_SIZE];
    while ((r = != -1) {
    output.write(buf, 0, r);

    output = null;
    input = null;

    Posted 09 Dec 2011 at 02:07
  3. John Dell'Aera wrote:

    For example, I can create files with Greek characters from a terminal via touch and all the UTF-8 characters are displayed correctly.

    Posted 09 Dec 2011 at 02:31
  4. Dominic Mitchell wrote:

    I’m not entirely sure how filenames are interpreted. It may well be independent of sun.jnu.encoding. In an example I just concocted, it appears to always use UTF-8 for filenames on my mac.

    Posted 10 Dec 2011 at 22:23