如何判断系统属性是来自人工操作员,而不是默认?

时间:2011-05-12 03:17:51

标签: java process processbuilder system-properties

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

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

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

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

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

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

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

有没有人有更好的选择?

3 个答案:

答案 0 :(得分:2)

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

不是通过命令行使用户提供系统属性(或者,在我们的例子中,使脚本中的行更长时间地启动应用程序的另一个属性),我们默认添加了对加载.properties文件的支持。

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

尽管如此,您可能会看到调试方案,其中需要临时或一次性属性而无需修改文件(并不是真的很重要)。你有几个选择:

  1. 继续使用您目前的方法。
  2. 让用户将系统属性作为的命令行参数传递,然后加载到父进程和子进程的系统属性中。
  3. 说难,请使用该文件。 (这不是一个可怕的事情,但作为用户,我会对该解决方案感到恼火)

答案 1 :(得分:1)

我认为没有一个好的答案。但幸运的是,大多数的标准系统属性要么无法覆盖,要么心智正常的人都不会覆盖。

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

  • 传递您认为传递的标准属性的子集,
  • 提供了一种指定用于子JVM的JVM选项(包括-D选项)的方法,或
  • 上述方法的组合。

答案 2 :(得分:1)

选择解决方案:

我仍然不得不使用一个子进程,该进程除了传递父进行比较的所有系统属性之外什么都不做。我偶然发现的唯一小问题是line.separator属性导致我的行读取代码在额外的空行上绊倒。这很容易解决。

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

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

我对用户没有太大的力量告诉他们应该通过属性文件或特殊的命令行参数传递Java系统属性。这很尴尬,违背了操作规范(特殊情况总是很糟糕)。

我也不能选择要传递给子进程的系统属性的子集。系统类文档没有告诉哪些可以覆盖(并且常识不替换任何文档)。最终用户还有一个设施可以定义他们自己的属性,而我无法用名称来预测那些属性。