为什么它会锁定lib/modules?

Tho*_* S. 22 java windows java-9

当我从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"});
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

有点像Java 9的bug(报告为JDK-8194734),但有一种解决方法可以在Windows上启动应用程序而不锁定lib\modules文件,例如使用外部(代理)应用程序,只需将传递的参数作为应用?

Cod*_*ard 5

修复了这个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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

SysInternals PsExec不会将文件继承到以它开头的进程中.记得使用-d参数,否则PsExec本身会保存文件.

使用cmd.exeas代理是不可能的,因为它总是继承句柄.

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

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