@Snowbuilder's answer put me in the right track, however it was mysteriously not working with Oracle JDK 1.8.0_231 (he tested with minor version _144). Even though I was able to update the underlying Map (validated by printing out System.getenv() before and after adding a new property to the Map), the changes were not reflected when the new property was retrieved using System.getenv("property").
After some investigation I found out that's because System.getenv() and System.getenv("property") end up using different static attributes of java.lang.ProcessEnvironment, which are initialized in the class' static block. So it doesn't matter if new properties are added to the Map retrieved using System.getenv(); these properties will not be available in the other Map used by System.getenv("property").
So I changed the code from the other answer to deal with this scenario and came to the code below. Please note this will only work if you retrieve properties using System.getenv("property"); if you use System.getenv().get("property") then his answer is what you need. The usage is as follows:
@SuppressWarnings("unchecked")
private static Map<String, String> getModifiableEnvironment() throws Exception
{
Class<?> pe = Class.forName("java.lang.ProcessEnvironment");
Method getenv = pe.getDeclaredMethod("getenv", String.class);
getenv.setAccessible(true);
Field props = pe.getDeclaredField("theCaseInsensitiveEnvironment");
props.setAccessible(true);
return (Map<String, String>) props.get(null);
}
This method should be used as follows:
getModifiableEnvironment().put("propName", "propValue");
System.getenv("propName"); // this will return "propValue"