2

Is it possible to retrieve the modified value of an environment variable in a Java program?

I tried using System.getenv(). But the new value is not reflected in the program. The scenario is this:

  1. The program retrieves the value of an environment variable.

  2. The value of this variable is changed externally, while the program is still running. (It could be even manual process, like for eg, in Windows, the user changes the value from Advanced tab in My Computer->properties)

  3. The program retrieves the value of the environment variable again.

The second time the value is retrieved, it should get the modified value. I found that using System.getenv() gave me the old value only. Is there any reliable method for this? (This requirement is specific to Windows, but would love to hear general solutions too)

vaisakh
  • 1,041
  • 9
  • 19

4 Answers4

2

Afaik, environment variables visible to a process are set up at process creation time.

Subsequent modifications to the OS variables are not visible to process other than that who change them.

However, depending on the OS, there could be some way to retrieve them. E.g. on Windows Os, they are kept in the registry, so you can read from them.

Try reading the key at HKCU\Environment for current user variables, and the key

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment for system variables.

See this question about Windows registry for a useful class to read the registry.

Community
  • 1
  • 1
Andrea Parodi
  • 5,534
  • 27
  • 46
2

No process watches the environment variables from the parent. Even C programs don't "watch" environment variables because you'd need to change it in that process. When a process starts up it gets a copy of the environment from its parent. So if you modify the environment variable in the parent it doesn't change the child processes version. Unless you start a new process of which it gets a copy of the change. And I think that's ultimately why Java doesn't see the changes because it behaves just like any normal process would. There is good reason for this behavior! If env variables were modifiable then you'd be getting into concurrency issues around them and you'd need to define when a process would "see" those changes from other processes. This is all about locking, visibility, and nasty issues of concurrency most OS didn't want to solve in the early days.

If you want to share data between two processes you have to use IPC (interprocess communication) to do so. In C land there were several ways to do this pipes, shared memory, sockets. Java simplified IPC to sockets because it was a superset of the abilities of the other two and transparency between remote and local processes. You can use pipes to share data with a Java process, but it would be through stdin.

Bottom line start socket in Java and send it data from another process.

chubbsondubs
  • 37,646
  • 24
  • 106
  • 138
  • Right, concurrency issues do crop up. Here though, we specifically ask the user to change the value and come back to the program. For that, IPC could be an overkill..Will certainly keep this option in mind as a fallback. – vaisakh May 03 '12 at 17:05
  • That would essentially mean restart the app. Prompt the user then shutdown the process and restart it. Viola you'll see the new value. This could easily be done through a watch dog type process that can restart the Java process. – chubbsondubs May 03 '12 at 20:46
1

In addition to answer by @Andrea Parodi (+1) I can really recommend you to either read environment by running external command line echo %MYENV_VAR% and read the output or read registry.

Please take a look on this article where I show how to read windows registry without any external libraries.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Reading registry seems promising. Now that I come to think of it, our framework provides us API to access registry values. I better take a look it. Thanks for the idea!(+1) – vaisakh May 03 '12 at 16:59
1

On Win 7, something like this will get the env vars:

Process p = Runtime.getRuntime().exec("cmd.exe /c set");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while( (line = br.readLine()) != null ) {
   String var = br.readLine();
   . . . .

I suspect its platform dependent though, so portability of your code will be a problem.

mazaneicha
  • 8,794
  • 4
  • 33
  • 52
  • Okay, the `set` command will work in Windows XP too. So that's not an issue, but I will have to parse the output to get the value. Worth a try nevertheless. – vaisakh May 03 '12 at 16:51
  • If it feels like too much work and if you're looking for a particular known var, try using `cmd.exe /c echo %YOUR_VAR_NAME%`. I thought you wanted to detect all changes. – mazaneicha May 03 '12 at 17:03
  • Yes, it is a known value; just a single variable – vaisakh May 03 '12 at 17:11