Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I find complete list of platform-dependent traps in JDK like timezone, encoding, line endings etc.?

We always want our dev/test environment to be production like, but often we can be caught in the trap of using JDK functions that are not exposing environment dependency very explicit (like required method parameter) or can be subtle to detect and be aware. For example:

  • public String(byte bytes[]) uses default encoding
  • new Date()/Instant.now() uses sytem timezone
  • System.out.printf("%n") uses platform line endings

Some of them can be driven by JVM parameters like -Dfile.encoding=UTF-8.

But how to find all of such gotchas?

like image 722
Piotr Müller Avatar asked Aug 28 '16 08:08

Piotr Müller


3 Answers

The type of gotchas depends on the type of your application.

For an almost complete list you can run this check, which lists both your operating system environment variables and the java system properties:

import java.awt.GraphicsEnvironment;
import java.util.Map;
import java.util.Properties;

public class Sof39189179 {

    public static void main(String[] args) {

        Map<String, String> sysenv = System.getenv();

        for(String key: sysenv.keySet())
            System.out.println( key +  ": " + sysenv.get(key));

        Properties properties = System.getProperties();

        for(Object key: properties.keySet())
            System.out.println(key + ": " + properties.get(key));

        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
        System.out.println("headless: " + ge.isHeadless());
    }
}

On my computer, I get the following output (I have left out some lines):

M2: $M2_HOME/bin
JAVA_HOME: /opt/local/jdk-1.8.0_51
LANG: en_US.UTF-8
CATALINA_HOME: /opt/local/tomcat-8.0.24

...

---------------------
java.runtime.name: Java(TM) SE Runtime Environment
sun.boot.library.path: /opt/local/jdk-1.8.0_51/jre/lib/amd64
java.vm.version: 25.51-b03
java.vm.vendor: Oracle Corporation
java.vendor.url: http://java.oracle.com/
path.separator: :
java.vm.name: Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg: sun.io
user.country: US
sun.java.launcher: SUN_STANDARD
sun.os.patch.level: unknown
java.vm.specification.name: Java Virtual Machine Specification
user.dir: /home/rudolf/workspace/neon/sof39189179
java.runtime.version: 1.8.0_51-b16
java.awt.graphicsenv: sun.awt.X11GraphicsEnvironment
java.endorsed.dirs: /opt/local/jdk-1.8.0_51/jre/lib/endorsed
os.arch: amd64
java.io.tmpdir: /tmp
line.separator: 

java.vm.specification.vendor: Oracle Corporation
os.name: Linux
...

java.awt.printerjob: sun.print.PSPrinterJob
file.encoding: UTF-8
java.specification.version: 1.8
java.class.path: /home/rudolf/workspace/neon/sof39189179/bin
user.name: rudolf
java.vm.specification.version: 1.8
java.home: /opt/local/jdk-1.8.0_51/jre
sun.arch.data.model: 64
user.language: en
java.specification.vendor: Oracle Corporation
awt.toolkit: sun.awt.X11.XToolkit
java.vm.info: mixed mode
java.version: 1.8.0_51
java.ext.dirs: /opt/local/jdk-1.8.0_51/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path: /opt/local/jdk-1.8.0_51/jre/lib/resources.jar:/opt/local/jdk-1.8.0_51/jre/lib/rt.jar:/opt/local/jdk-1.8.0_51/jre/lib/sunrsasign.jar:/opt/local/jdk-1.8.0_51/jre/lib/jsse.jar:/opt/local/jdk-1.8.0_51/jre/lib/jce.jar:/opt/local/jdk-1.8.0_51/jre/lib/charsets.jar:/opt/local/jdk-1.8.0_51/jre/lib/jfr.jar:/opt/local/jdk-1.8.0_51/jre/classes
java.vendor: Oracle Corporation
file.separator: /
java.vendor.url.bug: http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding: UnicodeLittle
sun.cpu.endian: little
sun.cpu.isalist: 
headless: false

You can determine from this list what properties are relevant in your case and check your code for it. Or, better, code with those properties in mind.

System.out.printf("%n") uses platform line endings

I prefer using the properties listed above, i.e. for printing out a newline, I use something like:

String newline = (String) System.getProperties().get("line.separator");
System.out.println("newline: " +  newline);
like image 102
Rudolf Held Avatar answered Nov 08 '22 14:11

Rudolf Held


Since you're asking for a complete list: Every time you interact with the operating system or native libraries.

Every time you don't do pure computationlet's ignore strict math there can be differences. Sometimes they are minor and only occur in edge-cases and sometimes they're explicitly part of the API.

  • Start a new thread? Subject to OS limits.
  • Want to schedule a task with nanosecond accuracy? Subject to timer precision available on the platform.
  • File names? Depends on what the filesystem supports.
  • Open a socket? Available port ranges are configured by the OS.
  • ...

As general advise: Read the docs of the APIs you're using and know what OS features underpin them

like image 42
the8472 Avatar answered Nov 08 '22 13:11

the8472


Not the direct answer to your question, but -XX:+PrintFlagsFinal and -XshowSettings:all helps a lot in comparing different environments. These flags will show default (hardware/os dependent) jvm settings and env/system properties.

You will also need to compare os settings like environment variables, os limits/quotas, security settings, file system settings etc.

like image 2
vsminkov Avatar answered Nov 08 '22 13:11

vsminkov