【问题标题】:Set Java system properties with a configuration file使用配置文件设置 Java 系统属性
【发布时间】:2011-07-18 16:36:43
【问题描述】:

是否可以使用某种配置文件来初始化 Java 系统属性?

(即:您可以使用 jar 中的文件设置 java.library.path 吗)

编辑:澄清:我特别询问初始化系统属性到文件中的一个值,而不是稍后从虚拟机内部设置它们。是的,您可以在机器启动后非常轻松地将系统属性更改为您想要的任何值,但是 Java 系统类不会使用新值。

实际上,这意味着 System.setProperty 和 System.setProperties 对于加载本机库是无用的,因为 JNI 将始终使用 java.library.path 的原始值来加载库。我试图弄清楚是否有一个更干净的替代方案,而不是在任何地方的启动脚本中都放置 -Djava.library.path=whatever 。

【问题讨论】:

  • 您需要实现观察者模式。当属性文件更改时,您可以在管理屏幕上有一个按钮让系统读取新值或继续检查属性文件上的日期更改。
  • 绝对可以从任何地方为您自己的类加载本地库:OSGi 通过 Bundle-NativeCode 清单标头公开了一种方法来为捆绑包执行此操作。
  • 或使用 System.load(String filename) 与您想要的任何路径

标签: java properties java-native-interface


【解决方案1】:

有一种以编程方式设置 java.library.path 的方法,请参阅this

代码是在 ClassLoader 上设置 sys_path 字段的 hack,

System.setProperty( "java.library.path", "/path/to/libs" );

Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );

【讨论】:

  • 链接不见了
  • 这将在 JDK 16 上严重破坏,默认情况下内部被强封装。以正确的方式做事,而不是通过反思来干预。
【解决方案2】:

自己做会很简单:

public static void main(String[] args) {
    Properties p = new Properties();
    p.load(...); // Load the properties from a file in your jar
    for (String name : p.stringPropertyNames()) {
        String value = p.getProperty(name);
        System.setProperty(name, value);
    }
}

【讨论】:

  • OP 澄清:“我特别询问有关将系统属性初始化为文件中的值,而不是稍后从虚拟机内部设置它们。”
【解决方案3】:

使用JAVA_TOOL_OPTIONS 环境变量。 _JAVA_OPTIONS 也可能有效,但根本没有记录。 JAVA_TOOL_OPTIONS 的文档薄弱,但这里有一些链接:

使用示例:

set JAVA_TOOL_OPTIONS=-Dmy.property=sth

启动 JVM 时,您应该会看到一条消息:

Picked up JAVA_TOOL_OPTIONS: ...

【讨论】:

    【解决方案4】:

    据我所知,你无法初始化它们,但你绝对可以使用任何你想要的源将它们的值覆盖为你想要的任何值。

    【讨论】:

      【解决方案5】:

      我认为System.setProperty(key,value)在你的程序中对java.library.path没有用的原因是你的应用程序启动了,你需要在程序运行之前设置它。

      检查您的原生库,如果该库有任何未包含在java.library.path 中的依赖项,System.load 将失败,就好像System.setProperty(key, value) 无法按预期工作一样。

      【讨论】:

        【解决方案6】:

        您可以使用附加代码(JVM 的另一个实例)解析属性文件,将其输出重定向到 var 并将此变量用作 java 调用的参数。例如:

        public class SystemPropertyLoader {
         public static void main(String[] args) throws Exception {
            String file = args[0];//TODO check args
            Properties properties = new Properties();
            InputStream is = new FileInputStream(file);
            properties.load(is);
            is.close();
            StringBuilder builder = new StringBuilder();
            for (Entry e : properties.entrySet()){
                builder.append("-D");
                builder.append(e.getKey());
                builder.append('=');
                builder.append(e.getValue());
                builder.append(' ');
            }
            System.out.println(builder.toString());
         }
        }
        

        #!/bin/ksh
        properties_variable=$(java SystemPropertyLoader input.properties)
        

        【讨论】:

        • @DouglasTreadwell 是的,确实是这样,但 OP 询问“专门将系统属性初始化为文件中的值,而不是稍后从虚拟机内部设置它们。”
        猜你喜欢
        • 2011-03-21
        • 1970-01-01
        • 2017-10-11
        • 2015-09-21
        • 2016-02-07
        • 2019-01-25
        • 1970-01-01
        • 2014-02-04
        • 2019-02-01
        相关资源
        最近更新 更多