Is a Java Process which was created via Runtime.exec killed when the runtime that created the process dies? Or do I have to kill them manually, e.g. by installing a shut down hook and killing all remaining processes via Process.destroy. The javadoc only speaks about what happens when the runtime continues to exist.
A Java Process is created as a subprocess of the JVM. All operating systems that I know of kill subprocesses when the parent process terminates.
However, if the process you create forks its own processes, that are not its child processes (or are detached, e.g. in the case of Windows GUI applications), those may continue running after the JVM terminates. There is an issue possibly related to that described in this question.
Related
java.lang.ProcessBuilder.start() calls to java.lang.ProcessImpl.forkAndExec(), which is a native method. From what I learned in my Operating System class, a fork will basically create a clone of the process which called it. I have checked the PPID of processes created by ProcessBuilder.start() and confirmed that those PPIDs are equivalent to PID of current Java process.
However, ProcessBuilder.start() may run an arbitrarily process which share nothing with current Java process. So why does java.lang.ProcessBuilder.start() starts a new process by a fork()?
Why does ProcessBuilder.start() starts a process by a fork()?
Because if it didn't fork() a child process, then the subsequent execve() would replace the JVM's code and data with the code and data of the new command you are running.
Why?
Because that is how the fork() and execve() system calls work.
Why?
Because:
it allows the child process (prior to the exec) to set up the file descriptors for that the exec'd command will see, and potentially other things
it was designed that way back in ~1970's era UNIX, and there hasn't been a strong enough case do it (significantly) differently.
They could be many JVMs per Operative system or it is only one JVM per Operative System ? I also read that with "Runtime.exit()", we stop the execution of a JVM?
I'm a bit confuse because I've always thought that JVM is a machine that never stop working, always awaken waiting to be called for example by the "java App.class".
The JVM is an abstract concept, and there may be many running instances per Operating System. The implementation is usually through the Java Runtime Environment. And when exit is called, the runtime stops. The JVM can certainly stop. And (on most computers) it has to be explicitly started.
i'have always thougth that JVM is a machine that never stop working, always awaken waiting to be called for example by the "java App.class"
No, that is not how the JVM works. It's not a background process that is waiting to execute your Java programs. There is not always just one JVM running on one computer.
Whenever you start a Java program, a new JVM is started. When you have multiple Java programs running at the same time, you have multiple JVMs running. Each program is running in its own JVM.
System.exit() stops the JVM that is running the current Java application. It has no effect on other Java programs running on the same machine.
If you start a java app (directly or indirectly with the java shell command), then an instance of the JVM is created and started.
When the application finishes (either by reaching the end or through System.exit() then the JVM instance stops.
Of course, you can have multiple Java apps running simultaneously. Each will be in its own JVM instance.
They could be many JVMs per Operative system or it is only one JVM per Operative System ?
You can do either. You can run a JVM for each command, or you can use an application server to run your java applications. (You cna have more than one application server)
I also read that with "Runtime.exit()", we stop the execution of a JVM ?
This triggers the JVM to shutdown. The process does some work such as calling Shutdown Hooks after this is called.
i' m a bit confuse because i'have always thougth that JVM is a machine that never stop working,
It can be used that way. For example scala has a daemon compiler which is used to compile scala programs.
always awaken waiting to be called for example by the "java App.class".
When you run any program, (java or not) this always starts a new program. The only time this doesn't happen is for built in shell commands. e.g. set
A bit of background.
I maintain a mutation testing system for Java. A main process launches child processes that contain automatically modified versions of a program.
This could result in the code in the child process getting stuck in infinite loops, running out of memory or crashing in any number of ways.
When the system detects that this has happened the main process kills the child using process.destroy and recovers the analysis.
Earlier versions shut the child process down from inside using System.exit, but I changed to killing the child processes from the main one using process.destroy as this was more robust.
I've now had a bug report that the child processes are failing to fully shutdown in some (as yet un-reproduced) circumstance when the code uses spring's DefaultMessageListenerContainer.
I assume the issue in some way relates to blocking io, and the process getting into the kind of state that requires a kill -9.
The actual question
So the question is - is there a more reliable platform independent way of killing a process in java than process.destroy?
I'm developing an application that will run as a service. I have added a shutdown hook to the program to do some file cleanup. When I install the program as a service (on Linux as a daemon or as a Windows service) the shutdown hook executes correctly. However, when running in the IDE the shutdown hook is never executed. Is there a way to stop the running process in the IDE and have the shutdown hook execute?
Thanks,
Pablo
Unfortunately there is no way to do this within the current Netbeans system,since the kill methods for both types of app testing (Debug and Normal) both, well kill the process, giving it no chance to cleanup.
Depending on the architecture of your app you may be able to add a System.exit(0) call, but other than that you are stuck with opening it up in the console.
I disagree. A sigkill in unix or terminate process in windows by definition will kill the running process without giving any ability for the application to catch these events. This is necessary to terminate an unresponsive process. These signals should only be used when a process does not respond to a siginit (ctrl c) or a sigterm or end task in windows. NetBeans seems to be sending a sigkill rather than siginit or sigterm. As far as I'm concerned this is bad practice.
There should be a secondary option to kill the process however the primary end process button should be to send siginit or sigterm. Applications should anticipate the user hitting ctrl c or end task on their application and as a best effort cleanly close files/sockets and save persistent/state data. An application should not anticipate a sigkill or terminate process but rather be developed in such a way that a sigkill or terminate process are not necessary.
By NetBeans using these methods as the only means to terminate the application from the IDE is erroneous.
Nope. Don't cleanup your program using shutdown hooks. From the docs...
In rare circumstances the virtual machine may abort, that is, stop
running without shutting down cleanly. This occurs when the virtual
machine is terminated externally, for example with the SIGKILL signal
on Unix or the TerminateProcess call on Microsoft Windows. The virtual
machine may also abort if a native method goes awry by, for example,
corrupting internal data structures or attempting to access
nonexistent memory. If the virtual machine aborts then no guarantee
can be made about whether or not any shutdown hooks will be run.
When the contract says that there is no guarantee that your shutdown hooks will always be called, it is not advisable to use them for critical operations.
I want to exit a java process and free all the resources before it finishes its normal running, if a certain condition is meet. I dont however want to quit JVM, as I have other java programs running at the same time. Does return; do the above, or is there a better way to do it?
Thanks.
There is one JVM process per running Java application. If you exit that application, the process's JVM gets shut down. However, this does not affect other Java processes.
You need to understand the JVM mechanism and clarify the terminology.
Let's use the following as datum for the terminology.
Threads are divisions of concurrently processed flows within a process.
A process is an OS level thread. The OS manages the processes. A process is terminated by sending a termination signal to the OS management. The signal may be sent by the process itself or by another process that has the applicable privilege.
Within a process, you can create process level threads. Process level threads are normally facilitated by the process management of the OS, but they are initiated by the process and terminated by the process. Therefore, process level threads are not the same as processes.
An application is a collection of systems, programs and/or threads that cooperate in various forms. A program or process within an application may terminate without terminating the whole application.
Within the context of JVM terminology, program may be one of the following.
A program is run per JVM process. Each program consumes one JVM process and is invoked by supplying the classpath of java bytecode and specifying the main entry point found in the classpath. When you terminate a java program, the whole jvm process that ran that program also terminates.
A program is run per process level thread. For example, an application run within a tomcat or JEE server is run as a thread within the JEE process. The JEE process is itself a program consuming one JVM process. When you terminate an application program, the JEE process does not terminate.
You may initiate process level threads within a java program. You may write code that terminates a thread but that would not terminate the process (unless it is the last and only running thread in the process). The JVM garbage collection would take care of freeing of resources and you do not need to free resources yourself after a process level thread is terminated.
The above response is simplified for comprehension. Please read up on OS design and threading to facilitate a better understanding of processes and the JVM mechanism.
If the other threads running concurrently are not daemon threads, leaving main will not terminate the VM. The other threads will continue running.
I completely missed the point though.
If you start each program in a separate JVM, calling System.exit() in one of them will not influence the others, they're entirely different processes.
If you're starting them through a single script or something, depending on how it is written, something else could be killing the other processes. Without precise information about how you start these apps, there's really no telling what is going on.
#aix's answer is probably apropos to your question. Each time you run the java command (or the equivalent) you get a different JVM instance. Calling System.exit() in one JVM instance won't cause other JVM instances to exit. (Try it and see!)
It is possible to create a framework in which you do run multiple programs within the same JVM. Indeed this is effectively what you do when you run a "bean shell". The same sort of thing happens when your "programs" are services (or webapps, or whatever you call them) running in some application server framework.
The bad news is that if you do this kind of thing, there is no entirely reliable way make an individual "program" go away. In particular, if the program is not designed to be cooperative (e.g. if it doesn't check for interrupts), you will have to resort to the DEPRECATED Thread.stop() method and friends. And those methods can have nasty consequences for the JVM and the other programs running in it.
In theory, the solution to that problem is to use Isolates. Unfortunately, I don't think that any mainstream JVMs support Isolates.
Some common usecases leading these kind of requirements can be solved through tools like Nailgun, or Drip.
Nailgun allows you to run what appears to be multiple independent executions of a commandline program, but they all happen in the same JVM. Therefore repeated JVM start-up time does not have to be endured. If these execution interact with global state, then the JVM will get polluted in time and things start to break up.
Drip will use a new JVM for each execution, but it always keeps a precreated JVM with the correct classpath and options ready. This is less performant, but it can guarantee correctness through isolation.