如何在JVM启动后动态设置System属性,而不修改程序代码?

fnatzsnv  于 8个月前  发布在  其他
关注(0)|答案(1)|浏览(46)

我希望能够改变一个系统属性,而Java应用程序是在应用服务器内运行。我知道这可以通过java.lang.System.setProperty或添加-DpropertyName=value作为JVM标志来完成。
但是我想在运行时完成这项工作,而不修改应用程序代码。
有没有一种工具可以在运行时更改JVM中的系统属性,而不必更新应用程序代码(例如,仅仅通过在运行的进程中附加一个工具或使用JMX)?

qoefvg9y

qoefvg9y1#

其想法是将调用System.setProperty的代理附加到正在运行的应用程序。

**注意:**不需要修改应用代码。

下面是代理代码:

import com.sun.tools.attach.VirtualMachine;

public class SetProperty {

    public static void main(String[] args) throws Exception {
        String url = SetProperty.class.getProtectionDomain().getCodeSource().getLocation().toString();
        if (args.length < 2 || !url.startsWith("file:")) {
            System.out.println("Usage: java -jar setproperty.jar pid property=value");
            System.exit(1);
        }

        VirtualMachine vm = VirtualMachine.attach(args[0]);
        try {
            int startIndex = "\\".equals(System.getProperty("file.separator")) ? 6 : 5;
            vm.loadAgent(url.substring(startIndex), args[1]);
        } finally {
            vm.detach();
        }
    }

    public static void agentmain(String args) {
        int eq = args.indexOf('=');
        System.setProperty(args.substring(0, eq), args.substring(eq + 1));
    }
}

1.编译源代码:

javac -source 8 -taraget 8 SetProperty.java

1.创建包含以下内容的MANIFEST.MF文件:

Main-Class: SetProperty
Agent-Class: SetProperty

1.从编译的源代码和清单构建.jar文件:

jar cfm setproperty.jar MANIFEST.MF SetProperty.class

1.启动代理,传递目标进程ID和要设置的属性(JDK 9+):

java -jar setproperty.jar 1234 MyProperty=SomeValue

如果使用JDK 8,则需要将tools.jar添加到类路径:

java -cp setproperty.jar:$JAVA_HOME/lib/tools.jar SetProperty 1234 MyProperty=SomeValue

我准备了setproperty.jar,这样你就可以跳过步骤1-3,直接执行最后一个命令。

相关问题