为什么它会锁定lib / modules?

当我从Java 9应用程序启动任何第三方应用程序,例如记事本(但你可以采取其他任何东西),然后退出Java应用程序:

import java.io.*; public class LaunchNotepad { public static void main(String[] args) throws IOException { Runtime.getRuntime().exec(new String[] {"C:\\Windows\\notepad.exe"}); } } 

启动的第三方应用程序保持锁定Java 9的lib\modules文件。 这使得我们的Java应用程序很难使用私有JRE进行自我更新,因为无法重命名原始目录(包含JRE)。 这是ProcessExplorer(Sysinternals)的截图:

ProcessExplorer的屏幕截图,显示了Java 9启动的记事本过程

这有点像Java 9的错误(报告为JDK-8194734 ),但有一个解决办法,在Windows上启动应用程序而不锁定lib\modules文件 ,例如通过使用简单启动传递的外部(代理)应用程序参数作为应用程序?

我修复了这个bug 。 这算作解决方法吗? 🙂

否则,确实可以采用一些解决方法。

解决方法1:使用awt.Desktop

通过Java源代码扫描,我发现awt.Desktop可以为我们调用ShellExecute

不幸的是,此方法不允许传递命令行参数。 您可以将临时批处理文件写入磁盘并将其作为变通方法启动。

 import java.io.*; import java.awt.Desktop; public class LaunchNotepad { public static void main(String[] args) throws IOException { File program = new File("C:\\Windows\\notepad.exe"); Desktop.getDesktop().open(program); } } 

解决方法2:使用PsExec作为代理

SysInternals PsExec不会将文件inheritance到以它启动的进程中。 记得使用-d参数,否则PsExec本身会保存该文件。

不能使用cmd.exe作为代理,因为它始终inheritance句柄。

解决方法3:创建自己的代理

您将需要使用两个WINAPI中的一个: CreateProcess (指定bInheritHandles=FALSE )或ShellExecute 。

如果您有Oracle Java支持合同,则应通过支持渠道询问何时需要修复。

更新 – 基于https://bugs.openjdk.java.net/browse/JDK-8194734 ,目前的答案可能是“Java 11发布时”。 但Oracle可能会决定将修复程序反向移植到Java 9和10。

如果您真的非常渴望修复,请考虑执行以下操作:

  1. 下载OpenJDK源代码并构建自己的JVM。

  2. 弄清楚bug的位置。 你似乎知道它是什么,所以不难想出去哪里看。

  3. 开发修复bug。

  4. 将修补程序作为修补程序提供给OpenJDK项目。

这将增加在标准代码库及其产生的分布中更快地修复问题的可能性。 它还将为您提供内部测试以及愿意使用“固定”JVM的客户的解决方法。

我提到了一种可能的解决方法,包括重新编写您拒绝的代码。 还有其他人。 AFAIK没有任何解决方法,不涉及为您工作,无论如何。