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

Java 如何判断系统属性是否来自人工操作符,而不是默认值?,java,process,processbuilder,system-properties,Java,Process,Processbuilder,System Properties,我有一个JAR打包的独立应用程序,当执行时,它将自己解压到一个临时目录中,并在该目录中生成一个子进程。原因是一些第三方代码和配置假定数据文件是相对于当前工作目录找到的,而java没有chdir()方法,因此唯一的方法是切换子进程的工作目录 除系统属性外,所有操作都正常。操作员可能决定在命令行中指定一些系统属性,包括标准属性和与第三方配置相关的属性: java -Djava.io.tmpdir=/temp -Dsomething=else -jar foo.jar (parameters) 默认

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

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

java -Djava.io.tmpdir=/temp -Dsomething=else -jar foo.jar (parameters)
默认情况下,父java进程可用的系统属性不会传播到子进程。我应该自己做。这里我遇到了一个障碍:我无法分辨哪些属性是由操作符设置的,哪些属性是由JVM默认初始化的

以java.io.tmpdir为例。如果操作员已经提供了,他有很好的理由这样做(可能默认位置是“磁盘已满”)。我必须将它设置为子进程,否则它将失败。但我怎么知道它是否来自接线员?它可能只是默认值

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

到目前为止,我发现的唯一解决方法(相当糟糕的一种)是首先生成另一个子进程,而不带任何参数,然后让它通过管道将它拥有的所有系统属性返回给父进程。与父级具有的值匹配的值是默认值。其余的应该传递给worker子进程


有人有更好的选择吗?

我认为没有好的答案。但幸运的是,大多数标准系统属性要么不能被重写,要么他们头脑正常的人不会重写

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

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

    • 我认为没有好的答案。但幸运的是,大多数标准系统属性要么不能被重写,要么他们头脑正常的人不会重写

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

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

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

      我们没有通过命令行生成用户提供的系统属性(或者,在我们的例子中,将启动应用程序的脚本中的行再加长一个属性),而是在默认情况下添加了对加载.properties文件的支持

      如果您可以说服用户将永久属性放在那里,然后启动子进程,然后从文件加载,那么您就可以完全避免这个麻烦

      不过,您可能会看到调试场景,其中需要临时或一次性属性,而无需修改文件(这并不是什么大问题)。您在这里有几个选择:

    • 继续使用您当前使用的方法
    • 让用户将系统属性作为命令行参数传递,然后将其加载到父进程和子进程的系统属性中
    • 说强硬,用锉刀。(这不是一件可怕的事情,但作为一个用户,我会对这种解决方案感到恼火)

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

      我们没有通过命令行生成用户提供的系统属性(或者,在我们的例子中,将启动应用程序的脚本中的行再加长一个属性),而是在默认情况下添加了对加载.properties文件的支持

      如果您可以说服用户将永久属性放在那里,然后启动子进程,然后从文件加载,那么您就可以完全避免这个麻烦

      不过,您可能会看到调试场景,其中需要临时或一次性属性,而无需修改文件(这并不是什么大问题)。您在这里有几个选择:

    • 继续使用您当前使用的方法
    • 让用户将系统属性作为命令行参数传递,然后将其加载到父进程和子进程的系统属性中
    • 说强硬,用锉刀。(这不是一件可怕的事情,但作为一个用户,我会对这种解决方案感到恼火)

    • 选择的解决方案:

      我仍然需要使用一个子进程,它什么也不做,只是将要比较的所有系统属性传递给父进程。我遇到的唯一一个小问题是line.separator属性,它导致我的行读取代码在额外的空行上出错。这很容易解决

      为什么我不接受任何答案:

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

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

      我也无法选择要传递给子级的系统属性子集