1

我有一个 JAR 打包的独立应用程序,它在执行时会将自身解压缩到一个临时目录中并在该目录中生成一个子进程。一些第三方代码和配置的原因是假设数据文件是相对于当前工作目录找到的,而 java 没有 chdir() 方法,所以唯一的方法是为子进程切换工作目录。

一切正常,除了系统属性。操作员可能会决定在命令行中指定一些系统属性,包括标准属性和与第三方配置相关的属性:

java -Djava.io.tmpdir=/temp -Dsomething=else -jar foo.jar (parameters)

默认情况下,父 java 进程可用的系统属性不会传播给子进程。我应该自己做。在这里我遇到了一个障碍:我无法分辨哪些属性是由操作员设置的,哪些是由 JVM 默认初始化的。

拿那个 java.io.tmpdir 一个。如果运营商提供了它,他有充分的理由这样做(也许默认位置是“磁盘已满”)。我必须将其设置为子进程,否则它将失败。但是我怎么知道它是否来自运营商?它可能只是默认值。

我可以尝试将所有可用的系统属性设置为子进程。虽然它需要很长的列表,更糟糕的是,在命令行长度有限的某些环境中会失败。

到目前为止,我发现的唯一解决方法(非常邪恶的)是首先生成另一个子进程,根本没有任何参数,然后让它通过管道将它拥有的所有系统属性返回给父进程。与父级匹配的值是默认值。其余的应该传递给工作子进程。

有没有人有更好的选择?

4

3 回答 3

2

在我工作的地方,我们有一个缓慢增长的用户可以应用的系统属性列表,虽然我们不需要担心子进程,但我们确实有一个不同的问题:太多了。

我们没有让用户通过命令行来提供系统属性(或者,在我们的例子中,使启动应用程序的脚本中的行变得更长),我们添加了对默认加载 .properties 文件的支持。

如果您可以说服用户将永久属性放在那里,然后启动启动子进程的过程,然后从文件中加载,您可以完全避免头痛。

不过,您可能会看到需要临时或一次性属性而不修改文件的调试场景(并不是说这真的很重要)。您在这里有几个选择:

  1. 继续使用您当前的方法。
  2. 让用户将系统属性作为命令行参数传递,然后将其加载到父进程和子进程的系统属性中。
  3. 说强硬,使用文件。(这不是一件可怕的事情,但作为用户,我会对该解决方案感到恼火)
于 2011-05-12T03:40:06.363 回答
1

选择的解决方案:

我仍然不得不使用一个子进程,它什么都不做,只是将它要比较的所有系统属性传递给父进程。我偶然发现的唯一小问题是 line.separator 属性,它导致我的行阅读代码偶然发现额外的空行。这很容易解决。

为什么我没有接受任何答案:

以下答案中建议的方法是合理的,但没有一个是完全令人满意的。

我没有太多权力让用户告诉他们 Java 系统属性应该通过属性文件或特殊的命令行参数传递。这很尴尬并且违背了操作实践(特殊情况总是不好的)。

我也不能选择系统属性的子集传递给子进程。系统类文档没有说明哪些可以覆盖(常识代替没有文档)。最终用户还可以定义自己的属性,而我无法通过名称或编号来预测这些属性。

于 2011-05-23T03:29:32.113 回答
1

我不认为有一个很好的答案。但幸运的是,大多数标准系统属性要么不能被覆盖,要么没有人会覆盖。

因此,以下方法可能是您最好的选择:

  • 传递您认为有意义的标准属性的子集,
  • 提供一种方法来指定用于子 JVM 的 JVM 选项(包括 -D 选项),或者
  • 上述方法的组合。
于 2011-05-12T03:35:57.563 回答