Can we read the OS environment variables in Java? - java

My OS is windows7. I want to read the environment variables in my Java application. I have searched google and many people's answer is to use the method System.getProperty(String name) or System.getenv(String name). But it doesn't seem to work. Through the method, I can read some variable's value that defined in the JVM.
If I set an environment variable named "Config", with value "some config information", how can I get the value in Java?

You should use System.getenv(), for example:
import java.util.Map;
public class EnvMap {
public static void main (String[] args) {
Map<String, String> env = System.getenv();
for (String envName : env.keySet()) {
System.out.format("%s=%s%n",
envName,
env.get(envName));
}
}
}
When running from an IDE you can define additional environment variable which will be passed to your Java application. For example in IntelliJ IDEA you can add environment variables in the "Environment variables" field of the run configuration.
Notice (as mentioned in the comment by #vikingsteve) that the JVM, like any other Windows executable, system-level changes to the environment variables are only propagated to the process when it is restarted.
For more information take a look at the "Environment Variables" section of the Java tutorial.
System.getProperty(String name) is intended for getting Java system properties which are not environment variables.

In case anyone is coming here and wondering how to get a specific environment variable without looping through all of your system variables you can use getenv(String name). It returns "the string value of the variable, or null if the variable is not defined in the system environment".
String myEnv = System.getenv("env_name");

Related

Why System.getProperty doesn't return value from System variables in windows

I have this system variable
this code:
System.out.println(System.getProperty("area"));
returns null.
Could I get acces to system variables from java code through System.getProperty method ?
P.S
This is not a system variable but an environment variable. You can access these variables by using System.getenv().
System.getProperty() is used to return any variables set while starting the program. Example:
# java -Dmyproperty=myvalue MyProgram
System#getProperty gets you the system properties.
You can access the environment variables Map through System#getenv
System.out.println(System.getenv("area"));
Should get you your results.
EDIT:
Try and run the following code and check if your required variable appears in the console or the behavior is incosistent for other defined variables:
public static void main(String[] args) {
Set<String> envSet = System.getenv().keySet();
for (String env : envSet) {
System.out.println("Env Variable : " + env + " has value : "
+ System.getenv(env));
}
}
To list all Java System Properties Use, Then check if you have an area property:
Properties props = System.getProperties();
props.list(System.out);
See This example

How do I set the default locale in the JVM?

I want to set the default Locale for my JVM to fr_CA. What are the possible options to do this?
I know of only one option Locale.setDefault()
You can set it on the command line via JVM parameters:
java -Duser.country=CA -Duser.language=fr ... com.x.Main
For further information look at Internationalization: Understanding Locale in the Java Platform - Using Locale
From the Oracle Reference:
The default locale of your application is determined in three ways.
First, unless you have explicitly changed the default, the
Locale.getDefault() method returns the locale that was initially determined
by the Java Virtual Machine (JVM) when it first loaded. That is, the
JVM determines the default locale from the host environment. The host
environment's locale is determined by the host operating system and
the user preferences established on that system.
Second, on some Java runtime implementations, the application user can
override the host's default locale by providing this information on
the command line by setting the user.language, user.country, and
user.variant system properties.
Third, your application can call the Locale.setDefault(Locale)
method. The setDefault(Locale aLocale) method lets your application
set a systemwide (actually VM-wide) resource. After you set the default locale with this
method, subsequent calls to Locale.getDefault() will return the newly
set locale.
You can use JVM args
java -Duser.country=ES -Duser.language=es -Duser.variant=Traditional_WIN
In the answers here, up to now, we find two ways of changing the JRE locale setting:
Programatically, using Locale.setDefault() (which, in my case, was the solution, since I didn't want to require any action of the user):
Locale.setDefault(new Locale("pt", "BR"));
Via arguments to the JVM:
java -jar anApp.jar -Duser.language=pt-BR
But, just as reference, I want to note that, on Windows, there is one more way of changing the locale used by the JRE, as documented here: changing the system-wide language.
Note: You must be logged in with an account that has Administrative Privileges.
Click Start > Control Panel.
Windows 7 and Vista: Click Clock, Language and Region > Region and Language.
Windows XP: Double click the Regional and Language Options
icon.
The Regional and Language Options dialog box appears.
Windows 7: Click the Administrative tab.
Windows XP and Vista: Click the Advanced tab.
(If there is no Advanced tab, then you are not logged in with
administrative privileges.)
Under the Language for non-Unicode programs section, select the desired language from the drop down menu.
Click OK.
The system displays a dialog box asking whether to use existing
files or to install from the operating system CD. Ensure that you have
the CD ready.
Follow the guided instructions to install the files.
Restart the computer after the installation is complete.
Certainly on Linux the JRE also uses the system settings to determine which locale to use, but the instructions to set the system-wide language change from distro to distro.
There is another away if you don't like to change System locale but the JVM. you can setup a System (or user) Environment variable JAVA_TOOL_OPTIONS and set its value to -Duser.language=en-US or any other language-REGION you want.
You can do this:
And to capture locale. You can do this:
private static final String LOCALE = LocaleContextHolder.getLocale().getLanguage()
+ "-" + LocaleContextHolder.getLocale().getCountry();
You can enforce VM arguments for a JAR file with the following code:
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
public class JVMArgumentEnforcer
{
private String argument;
public JVMArgumentEnforcer(String argument)
{
this.argument = argument;
}
public static long getTotalPhysicalMemory()
{
com.sun.management.OperatingSystemMXBean bean =
(com.sun.management.OperatingSystemMXBean)
java.lang.management.ManagementFactory.getOperatingSystemMXBean();
return bean.getTotalPhysicalMemorySize();
}
public static boolean isUsing64BitJavaInstallation()
{
String bitVersion = System.getProperty("sun.arch.data.model");
return bitVersion.equals("64");
}
private boolean hasTargetArgument()
{
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
List<String> inputArguments = runtimeMXBean.getInputArguments();
return inputArguments.contains(argument);
}
public void forceArgument() throws Exception
{
if (!hasTargetArgument())
{
// This won't work from IDEs
if (JARUtilities.isRunningFromJARFile())
{
// Supply the desired argument
restartApplication();
} else
{
throw new IllegalStateException("Please supply the VM argument with your IDE: " + argument);
}
}
}
private void restartApplication() throws Exception
{
String javaBinary = getJavaBinaryPath();
ArrayList<String> command = new ArrayList<>();
command.add(javaBinary);
command.add("-jar");
command.add(argument);
String currentJARFilePath = JARUtilities.getCurrentJARFilePath();
command.add(currentJARFilePath);
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.start();
// Kill the current process
System.exit(0);
}
private String getJavaBinaryPath()
{
return System.getProperty("java.home")
+ File.separator + "bin"
+ File.separator + "java";
}
public static class JARUtilities
{
static boolean isRunningFromJARFile() throws URISyntaxException
{
File currentJarFile = getCurrentJARFile();
return currentJarFile.getName().endsWith(".jar");
}
static String getCurrentJARFilePath() throws URISyntaxException
{
File currentJarFile = getCurrentJARFile();
return currentJarFile.getPath();
}
private static File getCurrentJARFile() throws URISyntaxException
{
return new File(JVMArgumentEnforcer.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
}
It is used as follows:
JVMArgumentEnforcer jvmArgumentEnforcer = new JVMArgumentEnforcer("-Duser.language=pt-BR"); // For example
jvmArgumentEnforcer.forceArgument();

How to set an environment variable in Java using exec? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I set environment variables from Java?
I'm trying to set an environment variable, and read it back to verify it was actually set.
I've got the following :
import java.io.IOException;
public class EnvironmentVariable
{
public static void main(String[] args) throws IOException
{
Runtime.getRuntime().exec("cmd.exe set FOO=false");
String s = System.getenv("FOO");
System.out.println(s);
}
}
However, it appears that FOO is always null, meaning its probably not set correctly.
Do I have the exec command correct? The javadocs state it can take a string argument as the command.
Any ideas?
There are overloaded exec methods in which you can include an array of environment variables. For example exec(String command, String[] envp).
Here's an example (with proof) of setting an env variable in a child process you exec:
public static void main(String[] args) throws IOException {
String[] command = { "cmd", "/C", "echo FOO: %FOO%" };
String[] envp = { "FOO=false" };
Process p = Runtime.getRuntime().exec(command, envp);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String s = reader.readLine();
System.err.println(s);
}
However, that sets the variable in the env of the created process, not of your current (Java) process.
Similarly, if you are creating a process from Ant (as you mention in comments to aix) using the exec task, then you can pass environment variables to the child process using nested env elements, e.g.
<exec executable="whatever">
<env key="FOO" value="false"/>
</exec>
This won't work. When you start a new process, that process receives a copy of the environment. Any changes it then makes to environment variables are made within that copy, and at no point will become visible to the caller.
What are you actually trying to achieve?
By running "cmd.exe", you start a new process, which receives the new environment variable, however the java process does not get that new environment variable set this way.
In Unix/Windows, each process has it's own set of environment variables and inherits the environment variables from it's parent during process creation.
System.getenv() only returns the environment variables that were set when the process was started, as far as I see there is no way to change the environment variables of the java process itself.
The only way you can check if the set works is by starting a small batch script where you set and do the check in one process.
It's null because you launch another cmd.exe: it's a different environment from the one of your Java application (cf aix answer).
I don't think the Java runtime can change an environment variable: it can read them, but can't change them.
If you want to change a system property available in your executing JVM, use System.setProperty(String key, String value).

How to enumerate all environment variable in Java

System.getenv(name) needs the name of environment variable.
I am trying to call Runtime.exec(String[], String[], File), the secondary parameter need an array of environment variable, I am not sure whether subprocess will inherit environment variables from current process if I specified this parameter.
For example, if I pass new String[]{"NEWDIR=/home"} as secondary parameter and current java process has environment OLDDIR=/var, what is the return value of System.getenv("OLDDIR") in the subprocess?
updated:
Sorry, I have to use Java 1.4 and it seems that System.getenv() was introduced in 1.5?
Map<String, String> env = System.getenv();
for (String envName : env.keySet()) {
System.out.format("%s=%s%n", envName, env.get(envName));
}
System.getenv() will return a Map<String,String> with all of the environment variables.
But you could just as easily switch to ProcessBuilder which is a more convenient API to start new processes.
With ProcessBuilder you can simply call environment() and get a Map that contains existing environment variables and which you can manipulate how you want: i.e., if you add something to it, then that will be added to the new processes environment variables. If you remove something from it, it will not be present in the new process.
If you run an external shell, you can use it to set environment variables. e.g.
bash -c ENV1=hi ENV2=bye echo $ENV1 $ENV2
This only works if you have a UNIX shell (or cygwin)
You should migrate away from Java 1.4 and Java 5.0. Even Java 6 you might consider upgrading to Java 7.

Eclipse CDT: How to save project-wide environment variables programmatically (permanently)

I am able to create project-wide environment variables programmatically to Project properties -> C/C++ Build -> Environment page. However when I restart the workspace the environment variables are vanished.
The code I use to add new project-wide environment variables is here:
Global variables:
private ICConfigurationDescription cfgd = null;
private final MultiCfgContributedEnvironment ce = new MultiCfgContributedEnvironment();
Inside method:
ICConfigurationDescription[] cfgs;
cfgs = new ICConfigurationDescription[] {cfgd};
for (ICConfigurationDescription cfg : cfgs) {
ce.addVariable("PKG_CONFIG_LIBDIR", dir,
EnvironmentVariable.ENVVAR_APPEND, SEPARATOR, cfg);
}
I am looking for a way to keep the environment variables on the 'Environment page' after the workspace is restarted.
Another solution, without using the internal classes/APIs, is:
IContributedEnvironment environment = CCorePlugin.getDefault().getBuildEnvironmentManager().getContributedEnvironment();
ICProjectDescription projectDescription = CoreModel.getDefault().getProjectDescription(project, true);
ICConfigurationDescription config = projectDescription.getActiveConfiguration(); // or any other configuration...
// Add variable to project configuration
environment.addVariable("PKG_CONFIG_LIBDIR", dir, IEnvironmentVariable.ENVVAR_APPEND, null, config);
// Update project (description)
CoreModel.getDefault().setProjectDescription(project, projectDescription);
Note that using null instead of config adds the variable to the global/workspace environment.
Also note the different "operation", as defined in IEnvironmentVariable.
I solved my own question. I include the code here if someone else has the same problem.
The solution is to use StorableEnvironment which stores env. vars to XML.
UserDefinedEnvironmentSupplier fUserSupplier = EnvironmentVariableManager.fUserSupplier;
StorableEnvironment vars = fUserSupplier.getWorkspaceEnvironmentCopy();
vars.createVariable("PKG_CONFIG_LIBDIR", dir);
fUserSupplier.setWorkspaceEnvironment(vars);
Be aware though that
org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
org.eclipse.cdt.internal.core.envvar.UserDefinedEnvironmentSupplier;
Are internal API classes and therefore their use is not recommended because their implementation could change and affect the functionality of your code.

Categories

Resources