The reference implementation of Java, OpenJDK, has been open source since a long time now, which means we can look under the covers and see the minute implementation details of anything we find interesting or the API doesn’t fully specify. For example, let’s have a look at how the system properties like
java.io.tmpdir get their values.
Starting in the source code of the
getProperty method in the java.lang.System class, we see that the system properties are held in a private instance variable called props, and its values are filled by a native method called
initProperties. Its implementation we find in System.c, and the very first thing it does is call another function with the name
java_props_t *sprops = GetJavaProperties(env);
If you grep the OpenJDK source code for this function you’ll find it defined in two places: one for Windows and another for Solaris. (The source code under
solaris is also used on Linux.) What it does is define a static struct
sprops of type
java_props_t, fill its fields with values based on API calls to the OS, and the return it. The
initProperties function mentioned earlier takes this struct and combines its values with properties passed in from the command line to set the properties that Java’s
System.getProperty method will eventually return.
For example, this is how
java.io.tmpdir, the directory where temporary files are stored, gets its value: On Solaris and Linux the preprocessor mactro
P_tmpdir is used; if it’s not defined the hardcoded path
/var/tmp is used. On Windows the API function
GetTempPathW is used:
WCHAR tmpdir[MAX_PATH + 1]; /* we might want to check that this succeed */ GetTempPathW(MAX_PATH + 1, tmpdir); sprops.tmp_dir = _wcsdup(tmpdir);
The case for
os.name is similar: On Solaris and Linux the JVM calls the uname function:
struct utsname name; uname(&name); sprops.os_name = strdup(name.sysname);
On Windows it’s a little more complicated: The JVM calls the Windows API function
GetVersionEx which returns the OS version number, like 6.1, and this is then translated into the product name, like “Windows 7”, by checking a bunch of conditions.
Then the case for
file.encoding: On Linux and Solaris the encoding is obtained calling
nl_langinfo(CODESET). On Windows the
GetLocaleInfo function is used to get the “default ANSI code page”, and then the appropriate prefix is added to produce an encoding name such as
Ms932. Special handling is needed for some CJK encodings like EUC-JP or GBK on both platforms though.