difference between environment variables and System properties - java

iam using the below link to understand environment variables and system properties.
https://docs.oracle.com/javase/tutorial/essential/environment/env.html
The link says environment variables are set by OS and passed to applications.
When i fetch environment variables using System.getenv() it shows me lot of properties which i never set.
So it must be OS (im using macOS) which had set these properties.
Some of the properties in System.getenv() are MAVEN_CMD_LINE_ARGS, JAVA_MAIN_CLASS_1420, JAVA_MAIN_CLASS_1430.
My question is why would OS would like to set the java specific properties in environment variables? Ideally these should be set by JVM (in System.properties()).
P.S.: From whatever i have read on net i understand that environment variables are set by OS and System.properties() are set by JVM
Also if someone can point me to a good link on environment variable and System.properties it will be very helpful. Iam very confused between the two.

Environment variables is an OS concept, and are passed by the program that starts your Java program.
That is usually the OS, e.g. double-click in an explorer window or running command in a command prompt, so you get the OS-managed list of environment variables.
If another program starts your Java program1, e.g. an IDE (Eclipse, IntelliJ, NetBeans, ...) or a build tool (Maven, Groovy, ...), it can modify the list of environment variables, usually by adding more. E.g. the environment variable named MAVEN_CMD_LINE_ARGS would tend to indicate that you might be running your program with Maven.
In a running Java program, the list of environment variables cannot be modified.
System properties is a Java concept. The JVM will automatically assign a lot of
system properties on startup.
You can add/override the values on startup by using the -D command-line argument.
In a running Java program, the list of system properties can be modified by the program itself, though that is generally a bad idea.
1) For reference, if a Java program wants to start another Java program, it will generally use a ProcessBuilder to set that up. The environment variables of the new Java process will by default be the same as the current Java program, but can be modified for the new Java program by calling the environment() method of the builder.

Related

System.getenv() call in JVM

I am setting environment variable in my machine using export MY_KEY=foo. And I am trying to fetch it in JVM using System.getenv("MY_KEY"). This returns null. But running echo $MY_KEY shows foo on the terminal.
I have tried restarting the IDE. Doesn't work, still.
The environment variable is only available to sub processes of the shell that exported it. Did you start your IDE from that shell?
If you want the variable to be available all the time, you need to add it
to the /etc/profile file or create a extra file in /etc/profile.d. It depends on your operating system.

set permanent environment variables using java

I have a java application which runs on a linux machine many times at a single login. At the beginning of it, I need to set some environment variables for further use. I did that by appending my variables and their values at the end of both ~/.bashrc and ~/.profile files.
In order to make those variables permanent, I should call "source ~/.bashrc" or "source ~/.profile". The problem here is that the source command can not be called through java because of it's scope concerns.
In a single word: How can I set permanent environment variables on my linux machine at the begining of my java application?

Is it possible to "fool" java that an environment variable is set from the command line

I'm running in an environment where I can pass parameters but not set environment variables using a normal commandline.
I would like to set environment variables nevertheless. Is there an alternative way to "fool" java that an environment variable is set, e.g. using -D parameters?
(I'm running spark in oozie through hue; all in the Cloudera stack).
The java command itself doesn't seem to allow that. It has a -D parameter, but that sets Java 'system properties':
$ java -help 2>&1 | grep -A1 '\-D'
-D<name>=<value>
set a system property
Java system properties are a sort of Java properties. Like environment variables, java properties are key-value pairs, but aren't the same thing as environment variables: If your Java application reacts to a specific environment variable, setting a system property of the same name won't have any effect unless the application explicitly reacts to that property, too.
If your environment allows you to run arbitrary Java applications and if it allows your Java applications to execute other processes, you can write a little wrapper that sets the environment variables on a ProcessBuilder (see the question Arnon linked in his comment: How do I set environment variables from Java?) to then invoke java with your actual JAR from it. You could either hard-code the environment variables to set, or set them according to system properties the wrapper receives. (Or you could even implement your own shell in Java and pass a script to it.)
Though, if you can modify the source of that actual JAR, a much more idiomatic solution would be to make it itself react to properties instead of (or additionally to) environment variables. (Unless you have to control environment variables that the java command / the JVM reacts to rather than the JAR you'd like to run. Then this approach would not be applicable, of course.)
If you can run arbitrary Java code, you can create and run a Process using ProcessBuilder, including an environment of your choice.
Hence, write a java program that parses a command-line like
java -cp .... your.Prog FOO=BAR BAZ=BOOM command arguments ...
and starts command with the environment extended by FOO and BAZ
(Note that command could be java ...)

How to access system variable from inside Java program?

echo $MY_FILE prints "/path/to/some/file"
System.out.println(System.getenv("MY_FILE")); prints null
Additionally, when i print JAVA_HOME (from Eclipse), i too get null. From the shell it echoes /Library/Java/Home
Not sure whether this is relevant, but system i am running is a mac
Any hints?
You likely have not exported the environment variable. In most shells, variables declared in the shell are not exported into the environment of subprocesses unless you do so explicitly, either like this:
export MY_HOME=/somewhere/over/the/rainbow
Or when invoking the program:
MY_HOME=/somewhere/over/the/rainbow java com.example.MyApplication
Also keep in mind that the environment is not global, so changes you make to the environment only affect that process and its subprocesses. If you want to affect the environment of all processes on your system, this has to be configured specially. In most cases, exporting in the shell is what you want.
First try to access a system variable not created by you say
System.out.println(System.getenv("JAVA_HOME"));
If the above work, try rebooting your VM
It appears that environment variable are in some sort of cache, and rebooting is one method to refresh it.
The way to access an environment variable is precisely the way you're aware of. That code works just fine, and the results you receive accurately tell you about the execution environment of the JVM that you're asking the questions of. So,
Environment variables are not 'system variables': they don't have system-scope; changing them in a new terminal will not change them in the process that launches terminals, etc.
They are held by an OS process, and are copied to children of that process. So, children also do not change the environment variables of their parents, when they change their own.
If you launch Eclipse, and then set environment variables in .profile or whatever, and then JVMs launched from Eclipse do not reflect these settings, then you know that Eclipse does not launch a shell that reads your .profile before launching the JVM; it may invoke the shell so that it doesn't read .profile, it may invoke another shell altogether, it may launch the JVM directly, without involving a shell.
If you launch Eclipse after setting those variables, and see the same behavior, then you've learned the same of the process that launches Eclipse.
If you reboot after setting those variables, and see the same behavior, then you've learned the same about your windowing environment.
You can't learn that you're "doing it wrong" when you ask for the values of environment variables in Java, as you're actually doing it right.
You can explore your environment with System.getenv()

Adding environment variables using java program and able to see when I open environment tab from My Computer

I want to write java program which adds environment variables and when I open environment tab from MyComputer,then I should be able to see that...
This is what I have tried,but it gives java.lang.unsupportedexception
Map env = System.getenv();
env.put("abc", "pqr");
And One more try is below,it is not giving any error...But I can not see any value added when I open environment variables tablenter code here from My Computer.But When i sysout "env" variable it gives me all paths including myone also...But I need same thing to be shwon in environment variables tab...
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe","/c","set");
Map env = processBuilder.environment();
env.put("abc", "pqr");
Please help me guys...Thanks in Advance...
There are two ways. The first one is to call the Windows API to change/set the environment variable. You must look for the right Windows API function and call it from Java. However calling any Windows API from Java is a topic on its own.
The second way is to call the setx.exe program with the correct arguments to set environment variables. Check the manual of the setx.exe program how to use it (and when it is installed) to set your environment variables.
In both ways you obviously restrict your Java program to run on Windows systems only.

Categories