Reputation: 4305
I have created a Java application where the main method (start of the program) initiates a Process object and an object of MainWindow class which creates a JFrame.
public static void main(String[] args) throws Exception {
File file = new File("./access/run.bat");
ProcessBuilder process_builder = new ProcessBuilder("cmd", "/c", file.getName());
process_builder.directory(file.getParentFile());
Process process = process_builder.start();
MainWindow window = new MainWindow(process);
}
I would like to terminate (kill) the process which has been instantiated with a process.destroy() when the window has been closed. Here is some code of the MainWindow class:
public MainWindow(final Process process) throws TransformerException, ParserConfigurationException, Exception{
JFrame mainWindowFrame = new JFrame();
*****some code here*****
mainWindowFrame.addWindowListener(new WindowListener() {
public void windowClosed(WindowEvent arg0) {
process.destroy();
System.exit(0);
}
*****some code here*****
}
}
When the window is closed, unfortunately, the process is not killed...can anyone give me an explanation for this and a possible solution? Thanks!!!
Upvotes: 1
Views: 2503
Reputation: 8290
The Javadoc of the Process
class says this :
The subprocess is not killed when there are no more references
to the Process object, but rather the subprocess
continues executing asynchronously.
There is no requirement that a process represented
by a Process object execute asynchronously or concurrently
with respect to the Java process that owns the Process object.
After searching on the Internet, it seems that it's a issue in the Java platform since Java 1.3. I found this blog entry that explains many issues about Process
in Java.
The problem is that the process
becomes an orphan after killing the application. In your code, you are killing the Process
from the GUI since the GUI (the MainWindow class) has its own thread and it is not the Process
parent. It's a parent/child problem.
There are two ways to correct that :
Since the main thread is the parent process, so the main thread must call the destroy
method. So you must keep a reference to the process
object.
The second way is to create the process while launching the MainWindow
. In the argument of the MainWindow class, you can pass the arguments of the process. So when the windowClosed
method is called, if the MainWindow is closed, the Process
will be destroy since the latter is the children of the MainWindow.
Upvotes: 0
Reputation:
According to the documentation here then windowClosed is called only if the window is disposed. To do that, you can either call dispose on the window or set the default close operation: in your code, after creating the JFrame, add the following:
mainWindowFrame.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
After looking at your code, I suggest you work differently:
in your listener, you are destroying the process and then exiting. therefore, you can set the deafualt close operation to exit and then implement the process destroying in the
implementation of windowClosing method : modifying the code of MainWindow to the following:
public MainWindow(final Process process) throws TransformerException, ParserConfigurationException, Exception{
JFrame mainWindowFrame = new JFrame();
mainWindowFrame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
*****some code here*****
mainWindowFrame.addWindowListener(new WindowListener() {
public void windowClosing(WindowEvent arg0) {
process.destroy();
}
*****some code here*****
}
}
Upvotes: 1