Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Change Environment Variables in Java [Snippet]

DZone's Guide to

How to Change Environment Variables in Java [Snippet]

Looking for a quick, dirty way to change environment variables in Java? Here's how to do it, but it relies on the JDK's internals, so be careful — it's really dirty!

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

And the second dirty hack for the day: How to change system environment variables in Java — at least during the lifetime of a JVM.

This can be useful when testing functionality that accesses environment variables set by container runtimes like Docker.

public class EnvironmentsTest {

    @Test
    public void testGetFoobar() throws Exception {
        assertNull(System.getenv("FOOBAR_ENV"));

        injectEnvironmentVariable("FOOBAR_ENV", "Foo");

        assertThat(System.getenv("FOOBAR_ENV"), is("Foo"));
    }

    private static void injectEnvironmentVariable(String key, String value)
            throws Exception {

        Class<?> processEnvironment = Class.forName("java.lang.ProcessEnvironment");

        Field unmodifiableMapField = getAccessibleField(processEnvironment, "theUnmodifiableEnvironment");
        Object unmodifiableMap = unmodifiableMapField.get(null);
        injectIntoUnmodifiableMap(key, value, unmodifiableMap);

        Field mapField = getAccessibleField(processEnvironment, "theEnvironment");
        Map<String, String> map = (Map<String, String>) mapField.get(null);
        map.put(key, value);
    }

    private static Field getAccessibleField(Class<?> clazz, String fieldName)
            throws NoSuchFieldException {

        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        return field;
    }

    private static void injectIntoUnmodifiableMap(String key, String value, Object map)
            throws ReflectiveOperationException {

        Class unmodifiableMap = Class.forName("java.util.Collections$UnmodifiableMap");
        Field field = getAccessibleField(unmodifiableMap, "m");
        Object obj = field.get(map);
        ((Map<String, String>) obj).put(key, value);
    }
}


This is a very dirty hack, that relies on the internals of the JDK, so please use it with care and, of course, only in testing scenarios. Also, this solution only works in more recent versions of JDK 1.8 — before that, the internal maps were split up and named differently.

You may want to consider changing your code to insert another abstraction for the environment setting — to make the configuration changeable.

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
jvm ,jdk 1.8 ,environment variables ,java

Published at DZone with permission of Sebastian Daschner, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}