如何用Java程序改变系统环境变量

 我来答
huanglenzhi
推荐于2016-09-13 · 知道合伙人数码行家
huanglenzhi
知道合伙人数码行家
采纳数:117538 获赞数:517190
长期从事计算机组装,维护,网络组建及管理。对计算机硬件、操作系统安装、典型网络设备具有详细认知。

向TA提问 私信TA
展开全部
  最近在做一个项目的时候,遇到一个要在java程序中改变linux的PATH环境变量的问题。我们知道在linux中PATH环境变量保存在用户根目录下的“.bashrc”和“.bash_profile这两个隐藏文件中。用户登录的过程中便会把这两个文件中的PATH路径记录的该用户的shell中。如果用户已经登录,这时可通过命令 export PATH=add_path:$PATH来增加一个路径为add_path的路径。但通过此种方式增加的PATH路径只在当前shell中有效(也就是说,当用户通过另一个shell登录时,PATH又变成了原来的值)。在windows中用户已经登录的情况下则是通过命令set来更改环境变量的。

  Java语言是一门跨平台的语言,具有一次编写到处运行的特点。在java的1.0版本中有System.getenv(String key)可以来取得操作系统的环境变量,但由于getenv()具有与操作系统紧密相关的特性,这与java的跨平台的跟本特征相冲突,所以在java1.2中该方法被不推荐使用。而程序员在编程的过程中经常需要用到getenv(),所以在java1.5中getenv()又重新回来了。虽然可以通过getenv()来取得系统的环境变量,但是却没有与getenv()相对应的setenv()函数来改变系统的环境变量。

  C语言是一门与平台相关的语言,在多年的发展中积累了数量相当可观的库函数,在stdlib.h函数库中就有getenv(参数省略)与setenv(参数省略)来获取和改变系统的环境变量,这就给我们一个提示:能不能在java语言中调用C语言的函数库?JNI(java本地接口)正给了我们这样一个选择。

  1.首先生成ChangeEnv.java文件

  /**
  * @author sgh
  * @version 1.0.0 06/07/21
  */
  public class ChangeEnv {

  /**
  * @param args
  */
  static {
  try{
  System.loadLibrary("change_env");//声明欲加载的动态链接库
  }
  catch(UnsatisfiedLinkError e ){
  System.err.println("Can not load library "+e.toString());
  
  }
  }
  public native void setEnv(String name ,String value, int replace);//声明一个本地调用接口
  
  }

  说明:

  1. 动态链接库在windows中是.dll文件,在linux中则是.so文件,但在System.loadLibrary("change_env")中不需要把后缀写出 ,程序会自己判断。
  2. 本地接口声明方式为在普通函数前加native关键字
  2. 编译java文件 :Javac ChangeEnv.java
  3. 使用命令 javah ChangeEnv 生成ChangeEnv.h文件(ChangeEnv.h文件由程序自动生成,程序员不需要作任何改动)
  /* DO NOT EDIT THIS FILE - it is machine generated */
  #include <jni.h>
  /* Header for class ChangeEnv */

  #ifndef _Included_ChangeEnv
  #define _Included_ChangeEnv
  #ifdef __cplusplus
  extern "C" {
  #endif
  /*
  * Class: ChangeEnv
  * Method: setEnv
  * Signature: (Ljava/lang/String;Ljava/lang/String;I)V
  */
  JNIEXPORT void JNICALL Java_ChangeEnv_setEnv
  (JNIEnv *, jobject, jstring, jstring, jint);

  #ifdef __cplusplus
  }
  #endif
  #endif

  说明:

  1.JNIEXPORT void JNICALL Java_ChangeEnv_setEnv
  (JNIEnv *, jobject, jstring, jstring, jint)是本地接口函数的声明需要在.cpp文件中实现它

  4.编写ChangeEnv.cpp

  #include"ChangeEnv.h"
  #include<stdio.h>
  #include<stdlib.h>
  //与ChangeEnv.h中函数声明相同
  JNIEXPORT void JNICALL Java_ChangeEnv_setEnv(JNIEnv * env, jobject obj, jstring name, jstring value, jint replace)
  {
  ////从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库函数
  setenv(name_char,value_char,replace);
  //通知虚拟机本地代码不再需要通过name_char访问Java字符串,否则会
  //造成内存泄露
  env->ReleaseStringUTFChars(name,(const char *)name_char);
  env->ReleaseStringUTFChars(value,(const char *)value_char);
  return ;
  }
  5.编译ChangeEnv.cpp文件,生成libchange_env.so文件
  gcc -I/home/disk4/sgh/sgh/jrockit/include -I/home/disk4/sgh/sgh/jrockit/include/linux -shared -o libchange_env.so ChangeEnv.cpp
  说明:
  1. Linux下链接库名称必须以lib开头,否则会无法识别
  6. 编写测试程序test.java
  import java.io.InputStreamReader;
  import java.io.LineNumberReader;

  public class test {

  /**
  * @param args
  */
  public static void main(String[] args) {
  // TODO Auto-generated method stub
  System.out.println(System.getenv("PATH"));//打印改变之前的PATH路径
  String pathPer = System.getProperty("java.library.path");
  pathPer+=":.";
  System.setProperty("java.library.path",pathPer);//把当前目录加到动态链接库路径中
  ChangeEnv changePath = new ChangeEnv ();//生成一个ChangeEnv对象
  changePath.setEnv("PATH","$PATH:/home/disk4/sgh/sgh/soft/slurm34/bin:/home/disk4/sgh/sgh/soft/slurm34/sbin",1);
  System.out.println(System.getenv("PATH"));//打印改变之后的PATH路径
  
  }

  }
  说明:
  1. 可以看到PATH路径发生了变化

  JNI在windows下的使用
  既然所有的.h ,.cpp文件都已写好,我们不防顺便编译以下windows下的动态链接库.dll文件。
  这时我们发现在windows下的vc环境中没有setenv(char * name ,char * value ,int replace),而只有putenv(char * key_value)函数,所以我们必须重写ChangeEnv.cpp,为了使ChangeEnv.class对外接口保持一致性,所以我们没有改写ChangeEnv.java中本地函数借口的声明。
  1. 重写ChangeEnv.cpp函数
  #include"ChangeEnv.h"
  #include<stdio.h>
  #include<stdlib.h>
  #include<string.h>
  //与ChangeEnv.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;
  strcat(key_value, "=");
  strcat(key_value, value_char);
  putenv(key_value);
  //通知虚拟机本地代码不再需要通过name_char访问Java字符串,否则会
  //造成内存泄露
  env->ReleaseStringUTFChars(name,(const char *)name_char);
  env->ReleaseStringUTFChars(value,(const char *)value_char);
  return ;
  }
  2. 在vc6中新建一个动态链接库工程,添加ChangeEnv.h和ChangeEnv.cpp到该工程中去
  3. 在“工具”----〉“选项-”----〉“目录”中添加java的include路径
  C:\Program Files\Java\jdk1.5.0_06\include和C:\Program Files\Java\jdk1.5.0_06\include\win32
  4. 单击“运行”,把生成的change_env.dll拷贝到ChangeEnv.java所在的工程目录中
  5. 在ChangeEnv.java所在工程中新建一个测试程序test.java
  import java.io.InputStreamReader;
  import java.io.LineNumberReader;

  public class test {

  /**
  * @param args
  */
  public static void main(String[] args) {

  ChangeEnv changePath = new ChangeEnv();
  changePath.setEnv("PATH", "%PATH%;c:\\", 1);
  System.out.println(System.getenv("PATH"));

  }

  }
转载
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式