Working with Java Environment Variables & 4 Ways to Set Variables

Java Environment Variables Blog Banner

What Are Environment Variables in Java? 

Environment variables in Java are external settings that influence system behaviors and configurations. They are useful for segregating environment-specific details from application code. These variables serve as parameters passed to the Java runtime environment, affecting its behavior or configurations without modifying the code. 

Operating systems like Windows, Linux, and macOS support these variables, allowing Java programs to adapt to different environments.

Environment variables are often used for managing project settings such as database configurations, API keys, and service endpoints. They avoid hardcoding sensitive data directly into the source code, increasing security and flexibility. This makes it easier to update settings without redeploying or altering the application’s codebase.

Use Cases for Environment Variables in Java 

There are several ways you can use environment variables in Java.

Storing API Keys

Environment variables are useful for securely storing sensitive information such as API keys. By keeping these keys out of the source code, developers ensure the security of their applications. Instead of hardcoding an API key directly in the code, it can be stored in an environment variable like API_KEY

In a Java application, you can access this key with:

String apiKey = System.getenv("API_KEY");

This approach ensures the API key is not embedded in the source code and not exposed in version control systems. Additionally, it allows easy updates to the key without modifying the codebase, making it possible to use different keys in different environments.

Defining Program Arguments

Environment variables can define program arguments, allowing applications to adapt their behavior based on the execution context. For example, a variable like ENV_MODE can indicate whether the application is running in development, testing, staging, or production mode:

String envMode = System.getenv("ENV_MODE");

In development mode, the application might enable verbose logging and debugging tools. In production, these features are typically disabled to enhance performance and security. This helps manage different configurations and behaviors dynamically, improving maintainability.

Setting Path Variables

Environment variables are also useful for setting path variables such as LOG_PATH or CONFIG_DIR. These variables specify directory paths for logging, configuration files, or other critical purposes. This flexibility allows applications to adapt to different environments without modifying the code:

String logPath = System.getenv("LOG_PATH");

For example, in a Java application, reading a configuration path from an environment variable allows it to adapt quickly to different file system layouts across development and production servers or different operating systems. This approach is particularly beneficial for applications that need to run on multiple platforms, where directory structures can vary.

Accessing Environment Variables in Java 

You can access environment variables in Java using the System class provided by the standard Java library. Use the System.getenv(String name) method to retrieve the value of a specific environment variable. 

Accessing an environment variable

For example, to access an environment variable named API_KEY, you would use:

String apiKey = System.getenv("API_KEY");

Handling missing values

It’s a good practice to check if the environment variable is null (i.e., not set) to avoid a potential NullPointerException. For example:

String apiKey = Optional.ofNullable(System.getenv("API_KEY")).orElse("defaultValue");

Alternatively, you can throw an exception if the environment variable is missing:

Optional.ofNullable(System.getenv("API_KEY"))
        .orElseThrow(() -> new IllegalStateException("API_KEY environment variable is not defined"));

Obtaining a map of all environment variables

To get a Map<String, String> of all environment variables, use System.getenv(). This is useful if you want to iterate over all available environment variables. For example:

Map envVars = System.getenv();
for (String envName : envVars.keySet()) {
    System.out.format("%s=%s%n", envName, envVars.get(envName));
}

Alternatively, this can be written in one line:

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

Setting Environment Variables in Java 

There are several ways to set environment variables in Java.

1. Using JUnit Pioneer Library

JUnit Pioneer is an extension pack for JUnit, a popular open source Java test framework. You can use JUnit Pioneer to easily set environment variables:

import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.SetEnvironmentVariable;

@Test
@SetEnvironmentVariable(key = "MY_ENV_VARIABLE", value = "MY_ENV_VARIABLE_VALUE")
void givenVariableSet_whenGetEnvironmentVariable_thenReturnsCorrectValue() {
    String actual = System.getenv("MY_ENV_VARIABLE");
    assertThat(actual).isEqualTo("MY_ENV_VARIABLE_VALUE");
}

This method uses the @SetEnvironmentVariable annotation to set the environment variable for the test method, making it easier to manage environment variables during testing.

2. Using JNI

Another method is to use the Java Native Interface (JNI) to set environment variables. This involves writing native code in C or C++ to interact with the operating system’s environment. Note that this approach has limitations such as platform dependencies and potential issues with Java runtime caching environment variables.

Here’s a basic example:

#include 
#include 

JNIEXPORT void JNICALL Java_SetEnv_setEnv(JNIEnv *env, jobject obj, jstring key, jstring value) {
    const char *nativeKey = (*env)->GetStringUTFChars(env, key, 0);
    const char *nativeValue = (*env)->GetStringUTFChars(env, value, 0);

    setenv(nativeKey, nativeValue, 1);

    (*env)->ReleaseStringUTFChars(env, key, nativeKey);
    (*env)->ReleaseStringUTFChars(env, value, nativeValue);
}

This JNI function sets an environment variable using the setenv function from the C standard library. 

The full process of setting environment variables with JNI is complex and outside our scope—it involves multiple steps including creating the Java class file, generating the header file, compiling C code into a shared library, and executing the Java main file.

3. Setting Variables for a Child Process

Using the ProcessBuilder class in Java, you can set environment variables for a child process. Here’s how you can do it:

import java.io.IOException;
import java.util.Map;

public class ChildProcessExample {
    public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder();
        Map environment = processBuilder.environment();
        environment.put("MY_ENV_VARIABLE", "MY_ENV_VARIABLE_VALUE");

        Process process = processBuilder.command("my-command").start();
        int exitCode = process.waitFor();
        System.out.println("Exit code: " + exitCode);
    }
}

This example sets an environment variable for the child process started by ProcessBuilder. It’s useful for scenarios where you need the environment variable to be available only within a specific subprocess.

4. Using Docker 

Docker is another useful way to manage environment variables for Java applications, especially for integration tests. You can define environment variables in the Dockerfile as follows. This Docker file is based on amazoncorretto, a free image created by Amazon that includes the Java Development Kit (JDK).

FROM maven:3.9.8-amazoncorretto-8-al2023
WORKDIR /app
COPY . /app
ENV MY_DOCKER_ENV_VARIABLE=TRUE
ENTRYPOINT ["mvn", "test"]

In your Java code, you can use libraries like Testcontainers to run tests inside a Docker container:

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;

class DockerEnvironmentTest {
    @Test
    void givenDockerEnvironment_whenGetEnvironmentVariable_thenReturnsCorrectValue() {
        try (GenericContainer container = new GenericContainer<>("my-docker-image")
                .withEnv("MY_ENV_VARIABLE", "MY_ENV_VARIABLE_VALUE")) {
            container.start();
            // My custom tests
        }
    }
}

This approach ensures that your environment variables are isolated within the container, providing a controlled environment for testing and deployment.

Related content: Read our guide to testing environment

Managing Java Environment Variables with Configu

Configu is a configuration management platform comprised of two main components, the stand-alone Orchestrator, which is open source, and the Cloud, which is a SaaS solution:

Configu Orchestrator

As applications become more dynamic and distributed in microservices architectures, configurations are getting more fragmented. They are saved as raw text that is spread across multiple stores, databases, files, git repositories, and third-party tools (a typical company will have five to ten different stores).

The Configu Orchestrator, which is open-source software, is a powerful standalone tool designed to address this challenge by providing confConfigu is a configuration management platform comprised of two main components, the stand-alone Orchestrator, which is open source, and the Cloud, which is a SaaS solution:

Configu Cloud

Configu Cloud is the most innovative store purpose-built for configurations, including environment variables, secrets, and feature flags. It is built based on the Configu configuration-as-code (CaC) approach and can model configurations and wrap them with unique layers, providing collaboration capabilities, visibility into configuration workflows, and security and compliance standardization.

Unlike legacy tools, which treat configurations as unstructured data or key-value pairs, Configu is leading the way with a Configuration-as-Code approach. By modeling configurations, they are treated as first-class citizens in the developers’ code. This makes our solution more robust and reliable and also enables Configu to provide more capabilities, such as visualization, a testing framework, and security abilities.

Learn more about Configu

Try Configu for free
Painless end-to-end configuration management platform
Get Started for Free