Java was touted as write once, run anywhere to emphasize its cross-platform advantages. Of course, the devil is in the details, and to interact with the local operating system, you still need to know something about it.

Without a built-in facility, the only real way to figure out the local OS is to try to exec commands unique to each OS and then check to see which ones succeed, and what value(s) get returned. For example, uname -a provides useful information on *nix systems, but is useless on Windows. It can be as painful as trying to find Waldo.

Fortunately, since different operating systems tend to have their own unique command sets and such, the designers of Java built in a convenient way of discerning the OS on which the JVM is running:

  String osName = System.getProperties().getProperty("os.name");

The values returned by the above snippet are:

  • AIX
  • Digital Unix
  • Free BSD
  • HP
  • Irix
  • Linux
  • Mac OS
  • Mac OS X
  • MPE/iX
  • Netware 4.11
  • OS/2
  • Solaris
  • Windows 2000
  • Windows 7
  • Windows 8
  • Windows 95
  • Windows 98
  • Windows ME
  • Windows NT
  • Windows Server 2008
  • Windows Vista
  • Windows XP

...and probably a few others.

How folks choose to use this information is where things start to fall apart.

For example, if you wanted to run a command in a subshell, in Win 95/98/... you run: command.com. In Win NT and forward, it's: cmd.exe. In *nix, it's: {c | k | tc}sh.exe, and so forth.

A. B.'s coworkers came up with:

  if (osName.indexOf("Windows 9") > -1) {  // Win-95, 98
     cmdBase = new String[3]; 
     cmdBase[0] = "command.com"; 
     cmdBase[1] = "/c"; 
     cmdBase[2] = "set"; 
  } else if ((osName.indexOf("NT")           > -1) || 
             (osName.indexOf("Windows 2000") > -1) ) { 
     cmdBase = new String[3]; 
     cmdBase[0] = "cmd.exe"; 
     cmdBase[1] = "/c"; 
     cmdBase[2] = "set"; 
  } else {// our last hope, we assume Unix 
     cmdBase = new String[3]; 
     String[] cmdConfigValue = new String[5]; 
     cmdConfigValue[0]=getProfileString("SYSTEM", "UNIX_ENV0", "/usr/bin/env"); 
     cmdConfigValue[1]=getProfileString("SYSTEM", "UNIX_ENV1", ""); 
     cmdConfigValue[2]=getProfileString("SYSTEM", "UNIX_ENV2", ""); 
     cmdConfigValue[3]=getProfileString("SYSTEM", "UNIX_SHELL0", "/bin/sh"); 
     cmdConfigValue[4]=getProfileString("SYSTEM", "UNIX_SHELL1", "-c");
     // construct cmdBase from the pieces
  }

I wonder what they'll do when Windows 9 comes out?