Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does it keep lib/modules locked?

When I launch any third-party application, e.g. Notepad (but you could take anything else), from a Java 9 application and then exit the Java application:

import java.io.*;

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

the launched third party application keeps locking Java 9's lib\modules file. This makes it hard for our Java application with a private JRE to update itself, because the original directory (containing the JRE) can't be renamed. Here's a screenshot from ProcessExplorer (Sysinternals):

Screenshot of ProcessExplorer showing the notepad process launched by Java 9

This smells like a Java 9 bug (reported as JDK-8194734), but is there a work-around for launching an application on Windows without locking the lib\modules file, e.g. by using an external (proxy) application that simply launches the passed parameter as an application?

like image 866
Thomas S. Avatar asked Jan 06 '18 20:01

Thomas S.


2 Answers

I fixed this bug. Does this count as a workaround? :)

Otherwise, some workarounds are indeed possible.

Workaround 1: Use awt.Desktop

Scanning through the Java sources, I found that awt.Desktop can call ShellExecute for us.

Unfortunately, this method does not allow to pass commandline arguments. You can write a temporary batch file to disk and launch it as workaround.

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);
  }
}

Workaround 2: Use PsExec as proxy

SysInternals PsExec does not inherit files into processes started with it. Remember to use -d parameter, or PsExec itself will hold the file.

Using cmd.exe as proxy is not possible, because it always inherits handles.

Workaround 3: Make your own proxy

You will need to use one of two WINAPI's: CreateProcess (specifying bInheritHandles=FALSE) or ShellExecute.

like image 123
Codeguard Avatar answered Dec 11 '22 01:12

Codeguard


If you have an Oracle Java Support contract, you should go through the support channels to ask when a fix will be forthcoming.

UPDATE - Based on https://bugs.openjdk.java.net/browse/JDK-8194734, the current answer is likely be "when Java 11 is released". But Oracle may decide to backport the fix to Java 9 and 10.

If you are really desperate for a fix, then consider doing the following:

  1. Download the OpenJDK source code and build your own JVM.

  2. Figure out where the bug is. You seem to know what it is, so it should not be hard to figure out where to look.

  3. Develop a fix for the bug.

  4. Contribute the fix to the OpenJDK project as a patch.

That will increase the likelihood of the problem being fixed sooner in the standard codebase and the distributions produced from it. It will also give you a workaround for in-house testing and for customers who are willing to use your "fixed" JVM.

I mentioned one possible workaround that involved reworking your code which you rejected out of hand. There are others too. AFAIK there are no workarounds that don't involve work for you, one way or another.

like image 41
Stephen C Avatar answered Dec 11 '22 01:12

Stephen C