1. Introduction

The package java.lang is automatically imported when in a Java application. This package contains many commonly used classes, from NullPointerException to Object, Math, and String.

The java.lang.System class is a final class, meaning that we can’t subclass it, and therefore, all methods are static.

In this tutorial, we’ll explore the differences between two System methods for reading system properties and environment variables. These methods are getProperty and getenv.

2. Using System.getProperty()

The Java platform uses a Properties object to provide information about the local system and configuration, and we call it System Properties.

System Properties include information such as the current user, the current version of the Java runtime, and the file path-name separator.

In the below code, we use System.getProperty(“log_dir”) to read the value of the property log_dir. We also make use of the default value parameter, so if the property doesn’t exist, getProperty returns /tmp/log:

String log_dir = System.getProperty("log_dir","/tmp/log");

To update System Properties at runtime, we use the System.setProperty method:

System.setProperty("log_dir", "/tmp/log");

We can pass our own properties or configurations values to the application using the propertyName command line argument:

java -jar jarName -DpropertyName=value

We set the property of foo with a value of bar in app.jar:

java -jar app -Dfoo="bar"

System.getProperty will always return a String.

3. Using System.getenv()

Environment Variables are key/value pairs like Properties. Many Operating Systems use Environment Variables to allow configuration information to be passed into applications.

The way to set an environment variable differs from one operating system to another. For example, in Windows, we use a System Utility application from the control panel, while in Unix, we use shell scripts.

When creating a process, it inherits a clone environment of its parent process by default.

The following code snippet illustrates using a lambda expression to print all Environment Variables:

System.getenv().forEach((k, v) -> {
    System.out.println(k + ":" + v);
});

getenv()* returns a read-only *Map. Trying to add values to the map throws an UnsupportedOperationException.

To obtain a single variable, we can call getenv with the variable name:

String log_dir = System.getenv("log_dir");

On the other hand, we can create another process from our application and add new variables to its environment.

To create a new process in Java, we can use the ProcessBuilder class, which has a method called environment. This method returns a Map, but this time the map is not read-only, meaning we can add elements to it:

ProcessBuilder pb = new ProcessBuilder(args);
Map<String, String> env = pb.environment();
env.put("log_dir", "/tmp/log");
Process process = pb.start();

4. The Differences

Although both are essentially maps that provide String values for String keys, let’s look at a few differences:

  1. We can update Properties at runtime, while Environment Variables are an immutable copy of the Operating System’s variables.
  2. Properties are contained only within the Java platform, while Environment Variables are global at the Operating System level, available to all applications running on the same machine.
  3. Properties must exist when packaging the application, but we can create Environment Variables on the Operating System at almost any point.

5. Conclusion

Although conceptually similar, the application of Properties and Environment Variables are quite different.

The choice between the two is often a question of scope. Using Environment Variables, the same application can be deployed to multiple machines to run different instances, and can be configured at the Operating System level, or even in AWS or Azure Consoles. This removes the need to rebuild the application to update the config.

Always remember that getProperty follows camel-case convention, and getenv doesn’t.