Más contenido relacionado La actualidad más candente (18) Similar a Java设置环境变量 (20) Java设置环境变量1. Java 设置环境变量
Zianed Hou
zianed@live.cn
1、Java设置环境变量的需求说明
2、Java获取环境变量
2.1 Java获取输出环境变量
2.2 Win下查看环境变量
2.3 Solaris10 下查看环境变量
3、Java环境变量实现机制的分析
4、Java设置环境变量的实现
4.1 使用ProcessBuilder 进行设置
4.2 直接使用新的环境变量组代替原先的
4.3 使用java执行期间的-D参数
4.4 在Runtime.exec中调用实现
4.5 使用JNI调用本地接口实现
Zianed Version 1.0 1
2. 1、Java设置环境变量的需求说明
在 Java 中只提供了 System.getenv()获取环境变量的方法,并没有提供动态的设置
环境变量的。
有时根据程序的需要需要动态的设置环境变量中的值以备使用。
当调用设置环境变量时:
import java.util.Map;
public class Env
{
public static void main(String[] args)
{
Map<String, String> env = System.getenv();
System.out.println("Env:");
for (Map.Entry<String, String> envEntry : env.entrySet())
{
System.out.println(envEntry.getKey() + " = " +
envEntry.getValue());
}
System.out.println("...");
env.put("zianed", "linary");
System.out.println(System.getenv("zianed"));
}
}
将抛出如下异常:
Exception in thread "main" java.lang.UnsupportedOperationException
at
java.util.Collections$UnmodifiableMap.put(Collections.java:1285)
at net.unixcenter.zianed.test.Env.main(Env.java:16)
使用示例如下:
在用户登录后将用户名和密码放置在环境变量中供其他程序的使用。
2、Java获取环境变量
获取对应的已经设置的环境变量的值
Zianed Version 1.0 2
3. public static String getenv(String name) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("getenv."+name));
}
return ProcessEnvironment.getenv(name);
}
获取全部的环境变量
public static java.util.Map<String,String> getenv() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("getenv.*"));
}
return ProcessEnvironment.getenv();
}
2.1 Java获取输出环境变量
//Env.java
import java.util.Map;
public class Env
{
public static void main(String[] args)
{
Map<String, String> env = System.getenv();
System.out.println("Env:");
for (Map.Entry<String, String> envEntry : env.entrySet())
{
System.out.println(envEntry.getKey() + " = " +
envEntry.getValue());
}
System.out.println("...");
}
}
Zianed Version 1.0 3
4. 2.2 Win下查看环境变量
C:Documents and SettingsZianed>set
ALLUSERSPROFILE=C:Documents and SettingsAll Users
ANT_HOME=D:apache-ant-1.7.1
APPDATA=C:Documents and SettingsZianedApplication Data
ClassPath=C:Program FilesJavajdk1.6.0_10lib;D:apache-ant-1.7.1lib;.
CLIENTNAME=Console
CommonProgramFiles=C:Program FilesCommon Files
COMPUTERNAME=ZIANED
ComSpec=C:WINDOWSsystem32cmd.exe
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=Documents and SettingsZianed
JAVA_HOME=C:Program FilesJavajdk1.6.0_10
LOGONSERVER=ZIANED
NUMBER_OF_PROCESSORS=2
OS=Windows_NT
Path=C:Program FilesCommon FilesNetSarang;C:Program FilesJavajdk1.6.0_10b
in;C:WINDOWSsystem32;C:WINDOWS;C:WINDOWSSystem32Wbem;C:Program
FilesATI
TechnologiesATI.ACECore-Static;C:Program FilesCommon FilesThunder NetworkK
anKanCodecs;C:Program FilesQuickTimeQTSystem;D:apache-ant-1.7.1bin;D:pro
gramoracle920bin;
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 15 Model 6 Stepping 5, GenuineIntel
PROCESSOR_LEVEL=15
PROCESSOR_REVISION=0605
ProgramFiles=C:Program Files
PROMPT=$P$G
QTJAVA=C:Program FilesJavajre6libextQTJava.zip
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:WINDOWS
TEMP=C:DOCUME~1ZianedLOCALS~1Temp
TMP=C:DOCUME~1ZianedLOCALS~1Temp
USERDOMAIN=ZIANED
USERNAME=Zianed
USERPROFILE=C:Documents and SettingsZianed
windir=C:WINDOWS
C:Documents and SettingsZianed>
Zianed Version 1.0 4
5. //输出结果如下:
Env:
USERPROFILE = C:Documents and SettingsZianed
PATHEXT = .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
JAVA_HOME = C:Program FilesJavajdk1.6.0_10
TEMP = C:DOCUME~1ZianedLOCALS~1Temp
SystemDrive = C:
ProgramFiles = C:Program Files
Path = C:Program FilesCommon FilesNetSarang;C:Program
FilesJavajdk1.6.0_10bin;C:WINDOWSsystem32;C:WINDOWS;C:WINDOWS
System32Wbem;C:Program FilesATI
TechnologiesATI.ACECore-Static;C:Program FilesCommon FilesThunder
NetworkKanKanCodecs;C:Program
FilesQuickTimeQTSystem;D:apache-ant-1.7.1bin;D:programoracle92
0bin;
HOMEDRIVE = C:
PROCESSOR_REVISION = 0605
CLIENTNAME = Console
USERDOMAIN = ZIANED
QTJAVA = C:Program FilesJavajre6libextQTJava.zip
ALLUSERSPROFILE = C:Documents and SettingsAll Users
PROCESSOR_IDENTIFIER = x86 Family 15 Model 6 Stepping 5, GenuineIntel
ClassPath = C:Program
FilesJavajdk1.6.0_10lib;D:apache-ant-1.7.1lib;.
SESSIONNAME = Console
TMP = C:DOCUME~1ZianedLOCALS~1Temp
CommonProgramFiles = C:Program FilesCommon Files
=:: = ::
LOGONSERVER = ZIANED
PROCESSOR_ARCHITECTURE = x86
FP_NO_HOST_CHECK = NO
OS = Windows_NT
HOMEPATH = Documents and SettingsZianed
PROCESSOR_LEVEL = 15
ANT_HOME = D:apache-ant-1.7.1
COMPUTERNAME = ZIANED
windir = C:WINDOWS
SystemRoot = C:WINDOWS
NUMBER_OF_PROCESSORS = 2
USERNAME = Zianed
ComSpec = C:WINDOWSsystem32cmd.exe
APPDATA = C:Documents and SettingsZianedApplication Data
...
Zianed Version 1.0 5
6. 2.3 Solaris10 下查看环境变量
root@test-177-ce0 # bash
root@test-177-ce0 # env
MANPATH=:/usr/man:/usr/share/man:/opt/SUNWvts/man:/opt/SUNWexplo/man:/opt/SUNWsnee
p/man:/opt/CTEact/man
SHELL=/sbin/sh
TERM=xterm
SSH_CLIENT=192.168.1.27 2077 22
SSH_TTY=/dev/pts/1
USER=root
LD_LIBRARY_PATH=/usr/openwin/lib
OPENWINHOME=/usr/openwin
MAIL=/var/mail//root
PATH=/bin:/usr/local/bin
_=/bin/env
PWD=/
EDITOR=vi
LANG=zh_CN.GBK
TZ=PRC
PS1=root@test-177-ce0 #
PS2=root@test-177-ce0 >
HOME=/
SHLVL=2
LOGNAME=root
SSH_CONNECTION=192.168.1.27 2077 192.168.1.177 22
root@test-177-ce0 #
输出结果如下:
root@test-177-ce0 # ls Env.java
Env.java
root@test-177-ce0 # javac Env.java
root@test-177-ce0 # java Env
Env:
XFILESEARCHPATH = /usr/dt/app-defaults/%L/Dt
LANG = zh_CN.GBK
PWD = /
SSH_TTY = /dev/pts/1
_ = /bin/java
SHLVL = 1
OPENWINHOME = /usr/openwin
NLSPATH = /usr/dt/lib/nls/msg/%L/%N.cat
MANPATH
Zianed Version 1.0 6
7. = :/usr/man:/usr/share/man:/opt/SUNWvts/man:/opt/SUNWexplo/man:/opt/SUNWsneep/man:/opt
/CTEact/man
USER = root
SSH_CLIENT = 192.168.1.27 2077 22
MAIL = /var/mail//root
EDITOR = vi
TZ = PRC
PS2 = root@test-177-ce0 >
HOME = /
PS1 = root@test-177-ce0 #
LD_LIBRARY_PATH =
/usr/jdk/instances/jdk1.5.0/jre/lib/sparc/server:/usr/jdk/instances/jdk1.5.0/jre/lib/sparc:/usr/jdk/inst
ances/jdk1.5.0/jre/../lib/sparc:/usr/openwin/lib
SSH_CONNECTION = 192.168.1.27 2077 192.168.1.177 22
TERM = xterm
SHELL = /sbin/sh
PATH = /bin:/usr/local/bin
LOGNAME = root
...
3、Java环境变量实现机制的分析
根据源代码的分析,可以发现 getenv 方法调用的是:
ProcessEnvironment.getenv(name);方法
查看其源代码发现如下:
final class ProcessEnvironment extends HashMap<String,String>
可见其本质是一个 HashMap 的键值对。
4、Java设置环境变量的实现
4.1 使用ProcessBuilder 进行设置
对子程序使用 ProcessBuilder 启用子程序进行设置环境变量,然后继承该子程
序即可实现子程序环境变量的设置。
Zianed Version 1.0 7
8. public class Env
{
public static void main(String[] args)
{
ProcessBuilder pb = new ProcessBuilder();
pb.command("set hello=world; ");
Map<String, String> map = pb.environment();
map.put("zianed", "linary");
Map<String, String> env = pb.environment();
System.out.println(env.get("zianed"));
}
}
4.2 直接使用新的环境变量组代替原先的
//MapEnv.java
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class MapEnv
{
public static void main(String[] args)
{
System.out.println("$zianed=" + System.getenv("zianed"));
Map<String, String> envMap = new HashMap<String, String>();
envMap.put("zianed", "zianed");
try
{
setEnv(envMap);
}
catch (Exception e)
{
System.out.println("出错啦");
e.printStackTrace();
}
System.out.println("$zianed=" + System.getenv("zianed"));
}
@SuppressWarnings("unchecked")
public static void setEnv(Map<String, String> newenv) throws
Zianed Version 1.0 8
9. Exception
{
Class[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for (Class cl : classes)
{
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName()))
{
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
Map<String, String> map = (Map<String, String>) obj;
map.clear();
map.putAll(newenv);
break;
}
}
}
}
输出如下:
$zianed=null
$zianed=null
可见此种方法并没有进行实质性的改变。
4.3 使用java执行期间的-D参数
java -cp <classpath> -Dkey1=value -Dkey2=value ...
// ChangeProperty.java
public class ChangeProperty {
public static void main(String[] args) {
System.out.println("Property$zianed=" +
System.getProperty("zianed"));
System.out.println("Env$zianed=" + System.getenv("zianed"));
}
}
测试如下
E:ZianedDesktopexercisejni>javac ChangeProperty.java
Zianed Version 1.0 9
10. E:ZianedDesktopexercisejni>java -Dzianed=zianed ChangeProperty
Property$zianed=zianed
Env$zianed=Zianed
-D 参数的一个巧妙使用
java 命令引入 jar 时可以-cp 参数, 但时-cp 不能用通配符(多个 jar 时什么
烦要一个个写,不能*.jar),面通常的 jar 都在同一目录,且多于 1 个。前些日
子找到(发现)-Djava.ext.dirs 太好。
java -Djava.ext.dirs=lib MyClass
4.4 在Runtime.exec中调用实现
And if you're innocent some other process passed it on to its child process,
just like you did in your Runtime.exec() call.
// RunTimeSetEnv.java
import java.io.IOException;
public class RunTimeSetEnv {
public static void main(String[] args) {
System.out.println("$zianed=" + System.getenv("zianed"));
try {
Runtime.getRuntime().exec("cmd set zianed=zianed");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("$zianed=" + System.getenv("zianed"));
}
}
输出如下:
$zianed=null
$zianed=null
可见是没有办法进行跨进程持久化的。
4.5 使用JNI调用本地接口实现
使用 C/CPP 编写本地接口语言文件设置环境变量,通过 JNI 调用实现。
Zianed Version 1.0 10
11. 1)编写调用的函数,生成 C 头文件
//ChangeEnv.java
public class ChangeEnv {
static {
try{
System.loadLibrary("changeEnv");//声明欲加载的动态链接库
}
catch(UnsatisfiedLinkError e ){
System.err.println("Can not load library "+e.toString());
}
}
public native void setEnv(String name ,String value, int replace);//声明一个本地调用接口
}
生成本地头文件
D:Microsoft Visual StudioMyProjectsChangeEnvDebug>javac ChangeEnv.java
D:Microsoft Visual StudioMyProjectsChangeEnvDebug>javah ChangeEnv
2)编写相关 C 代码实现功能
//Change.cpp
#include "ChangeEnv.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
JNIEXPORT void JNICALL Java_ChangeEnv_setEnv(JNIEnv * env,jobject obj,jstring
name,jstring value,jint replace){
if(replace==0)//如果 replace==0 表示不发生置换,直接退出
return ;
////从 instring 字符串取得指向字符串 UTF 编码的指针
const char * name_char =(const char *) env->GetStringUTFChars(name ,JNI_FALSE);
const char * value_char =(const char *) env->GetStringUTFChars(value ,JNI_FALSE);
//实际调用的 C 库函数,把环境变量写成 key=value 格式
char * key_value=(char *)name_char;
printf("1--------n");
printf("C$CLASSPATH=%sn",getenv("CLASSPATH"));
strcat(key_value, "=");
strcat(key_value, value_char);
printf("C$%sn",key_value);
putenv(key_value);
printf("1--------n");
printf("C$CLASSPATH=%sn",getenv("CLASSPATH"));
Zianed Version 1.0 11
12. printf("2--------n");
putenv("zianed=zianed");
printf("C$zianed=%sn",getenv("zianed"));
//通知虚拟机本地代码不再需要通过 name_char 访问 Java 字符串,否则会
//造成内存泄露
env->ReleaseStringUTFChars(name,(const char *)name_char);
env->ReleaseStringUTFChars(value,(const char *)value_char);
printf("Hello Dynamic Link Library has been calling!n");
return ;
}
编译的时间需要引入%JAVA_HOME%/include 和%JAVA_HOME%/include/win32 两个
头文件。然后将 dll 文件拷贝至工程中即可。
在 Unix/Linux 中,是要编译产生.so 文件
// ChangeEnv.cpp
#include "ChangeEnv.h"
#include <stdio.h>
#include <stdlib.h>
JNIEXPORT void JNICALL Java_ChangeEnv_setEnv(JNIEnv * env,jobject
obj,jstring name,jstring value,jint replace){
const char * name_chr = (const char
*)env->GetStringUTFChars(name,JNI_FALSE);
const char * value_chr = (const char
*)env->GetStringUTFChars(value,JNI_FALSE);
setenv(name_chr,value_chr,replace);
env->ReleaseStringUTFChars(name,(const char *)name_chr);
env->ReleaseStringUTFChars(value,(const char *)value_chr);
return ;
}
root@test-177-ce0 # gcc -fpic -c -I /usr/java/include -I /usr/java/include/solaris ChangeEnv.cpp
root@test-177-ce0 # ls -l ./
×ÜÊý 12
-rw-r--r-- 1 root root 746 1ÔÂ 2ÈÕ 14:45 ChangeEnv.class
-rw-r--r-- 1 root root 508 1ÔÂ 2ÈÕ 15:19 ChangeEnv.cpp
-rw-r--r-- 1 root root 435 1ÔÂ 2ÈÕ 14:46 ChangeEnv.h
-rw-r--r-- 1 root root 314 1ÔÂ 2ÈÕ 14:44 ChangeEnv.java
-rw-r--r-- 1 root root 1592 1ÔÂ 2ÈÕ 15:19 ChangeEnv.o
root@test-177-ce0 # gcc -G -o libchangeEnv.so ChangeEnv.o
Zianed Version 1.0 12
13. root@test-177-ce0 # ls -l ./
×ÜÊý 26
-rw-r--r-- 1 root root 746 1ÔÂ 2ÈÕ 14:45 ChangeEnv.class
-rw-r--r-- 1 root root 508 1ÔÂ 2ÈÕ 15:19 ChangeEnv.cpp
-rw-r--r-- 1 root root 435 1ÔÂ 2ÈÕ 14:46 ChangeEnv.h
-rw-r--r-- 1 root root 314 1ÔÂ 2ÈÕ 14:44 ChangeEnv.java
-rw-r--r-- 1 root root 1592 1ÔÂ 2ÈÕ 15:19 ChangeEnv.o
-rwxr-xr-x 1 root root 6932 1ÔÂ 2ÈÕ 15:21 libchangeEnv.so
其中的 libChangeEnv.so 就是所需要的 C 库文件。
3)测试运行
// TestChangeEnv.java
import java.io.InputStreamReader;
import java.io.LineNumberReader;
public class TestChangeEnv {
public static void main(String[] args) {
String pathPer = System.getProperty("java.library.path");
pathPer+=":.";
System.setProperty("java.library.path",pathPer);//把当前目录加到动态链接库路径中
System.out.println("Java$ClassPath="+System.getenv("ClassPath"));//打印改变之前的
PATH 路径
ChangeEnv changePath = new ChangeEnv ();//生成一个 ChangeEnv 对象
changePath.setEnv("ClassPath","%ClassPath%;C:",1);
System.out.println("Java$ClassPath="+System.getenv("ClassPath"));//打印改变之后的
PATH 路径
}
}
D:Microsoft Visual StudioMyProjectsChangeEnvDebug>java TestChangeEnv
Java$ClassPath=C:Program FilesJavajdk1.6.0_10lib;D:apache-ant-1.7.1lib;.
1--------
C$CLASSPATH=C:Program FilesJavajdk1.6.0_10lib;D:apache-ant-1.7.1lib;.
C$ClassPath=%ClassPath%;C:
1--------
C$CLASSPATH=%ClassPath%;C:
2--------
C$zianed=zianed
Zianed Version 1.0 13
14. Hello Dynamic Link Library has been calling!
Java$ClassPath=C:Program FilesJavajdk1.6.0_10lib;D:apache-ant-1.7.1lib;.
D:Microsoft Visual StudioMyProjectsChangeEnvDebug>
References
http://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java
http://www.developer.com/java/other/article.php/626151/Global-Variables-in-Java-with-the-Single
ton-Pattern.htm
http://bytes.com/topic/java/answers/782644-set-environment-variable-java
http://www.theserverside.com/news/thread.tss?thread_id=43397
http://hi.baidu.com/xiaoxxcool/blog/item/ba8a31d046f0fdd9572c84d7.html
http://www.blogjava.net/chenlb/archive/2008/06/22/209957.html
Zianed Version 1.0 14