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 encodingnew Date()/Instant.now()
uses sytem timezoneSystem.out.printf("%n")
uses platform line endingsSome of them can be driven by JVM parameters like -Dfile.encoding=UTF-8
.
But how to find all of such gotchas?
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);