为什么它会锁定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)的截图:
这有点像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。
如果您真的非常渴望修复,请考虑执行以下操作:
-
下载OpenJDK源代码并构建自己的JVM。
-
弄清楚bug的位置。 你似乎知道它是什么,所以不难想出去哪里看。
-
开发修复bug。
-
将修补程序作为修补程序提供给OpenJDK项目。
这将增加在标准代码库及其产生的分布中更快地修复问题的可能性。 它还将为您提供内部测试以及愿意使用“固定”JVM的客户的解决方法。
我提到了一种可能的解决方法,包括重新编写您拒绝的代码。 还有其他人。 AFAIK没有任何解决方法,不涉及为您工作,无论如何。