Reliably kill a process in Java - java

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?

Related

java Process fails if process is ptrace ATTACH

I'm having the strangest problem: maybe someone can help out.
I have a daemon written in Java (I've tried the latest Java 8 both OpenJDK and Oracle) on Linux. It will spawn some processes and there is a thread which watches to see if they're complete, meanwhile it will run other commands, some of which may kill the processes, etc.
Everything works absolutely fine almost all the time. However, one of the operations that the daemon can perform on its subprocesses is it can grab a core from them (without killing them: a core of the active process). It does this by loading a .so and calling it via JNI, which uses ptrace(PTRACE_ATTACH...) to pause the subprocess and grab core information, then it uses ptrace(PTRACE_DETACH...) to let it run again.
This also works fine and I can see the process operates correctly after the core has completed and all is fine.
Except, Java's Process object is now all wonky. Whenever I invoke exitValue() on this process once this has happened I always get back and exit code of 4991 (which if you decode it, means WIFSTOPPED with a signal value of 19, or SIGSTOP). That's not entirely surprising since the Linux man page states that ptrace() will look to parents as WIFSTOPPED. But the problem is that once the Process object reaches this state, it will never do anything else, even though the process actually goes back to running after the detach.
Even more critically, even after the process really exits, exitValue() still returns 4991, and the process is not reaped (it lives on in Z (zombie) state, as defunct) and will never go away, until my daemon is killed whereupon init will inherit, and reap, the zombie processes.
I've looked at the value of isAlive() (says no) and I've tried to run waitFor(0, TimeUnit.SECONDS) (says not running) but none of them get Process out of this broken state--this doesn't surprise me too much since my reading suggests these methods are actually implemented in terms of the exitValue() method anyway.
This appears to me like a bug in Java Process but I'm not sure... I've tried reproducing it by attaching GDB to the process then detaching it, but that doesn't show the same problem. Similarly just using SIGSTOP / SIGCONT doesn't do it.
Anyone have any hints or thoughts?

Spin up a report collection node.js app for my executable

I have a java project that runs for a long time since it has a lot of things to churn through (controlling other subprocesses and all).
I would like to display the progress of this executable on a webpage that I can access for the period of execution of the Java executable.
How do I spin up a Node.js server from my java excutable so that if the java executable exits, the server knows to also exit and save the report information so far somewhere. Also, am I doing something that others have done before?
You could set up a heartbeat (a signal from your java application), and have the node app look for that (as part of the data it processes from the java application, or as a separate message). When there is no data, you still need to send the heartbeat. But as long as it is a small message, it will hopefully not impact your performance significantly.
Then set the node server up to shutdown (or restart), and write out your exiting data, if the heartbeat is absent for a fixed amount of time.

Strange behavior re-runing java application in a loop

Unix daemon runs a script a loop, the script calls a java program: java {java_args} myClas.jar
The java program is heavy program with multiple threads.
The problem is very strange: First execution works as expected.
But the second execution is stuck some where and I can't find a reason (very hard to debug this).
Is there a possibility that when first execution is finished there are still not-cleaned resources or threads left from this execution?
If yes, is it possible to clean and kill everything right after process completes?
If by resources, you mean threads, then no. When the VM shuts down, everything on the heap, all threads, objects and monitors are disposed of. However if you're depending on the existence/absence of a file for locking or something similar, a deadlock is possible. Also, is it possible that the first process is still running when you launch the second one?
If your java process is stuck on the second run, you can attach jvisualvm to it and should be able to figure out where it's stuck.

Java exit a program without quitting JVM

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.

How to check whether an executable JAR has finished in another JVM

guys, I encounter a confusing issue! I want to invoke a executable JAR to compute PI from my main java applicaion using runtime.exec(), which create a new JVM for running the executable JAR. My issue is that when the PI computation is done, the JVM is still alive. my main java application has no idea whether PI computation is finished or not. And I also want when the PI computation is done, the JVM could be shutdown! How can I implement that! ThankS!!
When you call Runtime.exec() you will get a Process object back. You need to call waitFor() on this.
You will also need to capture the stdout/stderr streams (in separate threads to prevent blocking - see this answer for more info).
This all leaves aside why you're doing this in a separate JVM, and why you can't load the relevant classes into your current app and run the library locally.
To answer the second part of your question, the JVM always exits when no non-daemon threads are still running. Or in plainer speech, when your application is "done" and the main method exits without leaving any threads running in the background, the JVM will finish.
This is true regardless of whether you launch the Java process yourself from your desktop/command line, or fire it off via Runtime.exec() (which is broadly equivalent). So when your Pi calculation terminates it will shut down the JVM you spawned, and when your original program finishes then its JVM will also exit.
Though I agree completely with Brian here, I can't see the benefit in running a Java app as a separate process when you should be able to just run it in the original JVM (barring some really unusual environmental stuff such as setting niceness or processor affinity of the various processes).
check what the jar does when you run it standalone, maybe its waiting for input and therefor it will never exit

Categories