How can I catch moment when someone kill java.exe process? - java

console java application. Someone kill java.exe process by Task Manager. How can I write to logs some information at this moment before application is terminated?
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) { ..... }
});
OR
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() { ..... }
});
don't execute in such situation

This is not possible. Shutdown hooks will only be executed in an orderly shutdown:
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.
You can send another signal that will trigger an orderly shutdown like SIGINT. Killing a application should be the last resort after the application did not respond.

some practical solutions have already been suggested, but another is to ping-pong a "last status" message between 2 applications that monitor each other. When one dies, the other one writes the last received message to a log file. Users can't kill both processes quickly enough with Task Manager.

Some sort of solution is to write something to a log file all the time. This way you'll see whatever was the "last breath" of the Java program.

you might try to start java.exe via a small naive (e.g. c++) application using a CreateProcess (in windows ) this application will then continue running monitoring the java process handle. if the java process is gone it can log it.

Give your users an orderly way to shut down the system, and tell them to stop using Task Manager to do so.

Related

How to shutdown java application? [duplicate]

I'm interested in different approaches to gracefully shutting down a Java command line program. Sending a kill signal is not an option.
I can think of a few different approaches.
Open a port and wait for a connection. When one is made, gracefully shutdown.
Watch for a file to be created, then shutdown.
Read some input from the terminal, such as "execute shutdown".
The third one is not ideal, since there is often program output pumped to the screen. The first one takes too much effort (I'm lazy). Do most programmers use the second option? If not, what else is possible/elegant/simple?
you can try something like this:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() { /*
my shutdown code here
*/ }
});
edit:
the shutdown hook will not perform the shutting down of the app. instead, it gives the developer a way to perform any clean-up that he/she wishes at shutdown.
from the JavaDoc for Runtime (a good read if you are planning to use this method):
A shutdown hook is simply an initialized but unstarted thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt. ...
you could try to use Runtime.getRuntime().addShutdownHook() that should satisfy your requisite. In this way you can register an hook to do cleanups, in order to perfom a gracefull shutdown.
EDIT
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)
public void addShutdownHook(Thread hook)
Registers a new virtual-machine shutdown hook.
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
The benefit of the second option - checking for a file - over the first - listening on a port - is that you have some possibility of security.
You can set the permissions on the directory where the file is created so that only appropriate users can close the program. If you listen on a port any user can connect to it.
If you wanted to go with the socket version, it is very simple to implement. Here's the code:
ServerSocket server = new ServerSocket(8080);
System.out.println("Socket listening!");
server.accept();
System.out.println("Connection received!");
You could easily embed this code in a separate thread that you start with your program, and then have it modify global state to initiate shutdown.
The first two option is simple to implement. You could also use some JMX stuff (I don't know much about that). Tomcat uses the first approach and I applied 1 and 2 in two of my projects.
Consider having a JMX component. Then you can attach with JConsole either locally or over the network, and communicate with your component. Then the component can shut down the program properly.
With Java 6 u 10 or later, you can do the same with JVisualVM.
I would suggest to use the shutdown hook. It will allow your program do be controlled using standard OS tools. It also does not need any additional access to external resources (disk, ports, whatever).

How to call shutdown hook from storm topology main class?

i have a storm topology class which starts a kafka spout and bolts. This class is main class. I am trying to clean exit storm topology, so i have created a shutdown hook in side that topology main method.
//Shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Inside shutdown hook.");
Utils.sleep(1000000);
cluster.killTopology("netra-fault-management");
cluster.shutdown();
logger.info("Shutting down Topology.");
}
});
Here is my shutdown hook which is in main method of tolpology class. I run it from command prompt and when i do ctrl+c it is expected to run this shutdown hook but it just closes and no hook code is called . Do any buddy have idea about that how to run it on ctrl+c (SIGINT).
With Runtime#addShutdownHook, it is possible.
The problem should be caused by Utils.sleep(1000000);. You should not "sleep" the shutdown thread as The Java Virtual Machine(and other applications) doesn't allow it. A shutdown hook is designed to be called when the application is about to be closed, to save important stuffs or unload resources, etc. The Java Virtual Machine will terminate after few seconds, even the thread isn't executed completely.
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.
From JavaDoc for Runtime class. Sometimes the shutdown hook will not be called. Good luck!
See Nathan Marz commenting on a similar question years ago, I presume the behaviour has not changed:
https://groups.google.com/forum/#!topic/storm-user/A4-uFS6px2Y
Storm shuts down worker processes with SIGKILL, the JVM will not execute the shutdown hook under those circumstances (like it would for SIGINT).
As far as I understood from this and this, they've implemented a change allowing the shutdown hook to fire, but the hooks code is limited to one second, so OK for some scenarios. Hovewer, I didn't check personally as it's not enough for my case which is buffer upload. But there is alternative approach for me that I'm going to implement.

Java Runtime.exec communictation possible?

I have a main java program which should launch other java programs in an own process using Runtime.exec(), e.g.
Runtime.exec("java -jar myapp.jar");
Is there a possibility to communicate with this new process, e.g. sending request, chaing fields...?
How can I shutdown this new created process? I think I get an handler back and thus can kill the process. But is there a nicer way?
If I kill the process, will the shutdownhook still be executed before the process is killed?
Runtime.getRuntime().addShutdownHook
Is there a possibility to communicate with this new process, e.g. sending request, chaing fields...?
You can communicate with the process through the Process object returned by Runtime.exec. Just use Process.getInputStream/.getOutputStream.
If you want to invoke methods on the other Java process you could look into RMI ("Remote method invocation"). Another option is of course sockets. See this related answer.
There's no straight forward platform independent way of changing fields of the other Java process.
If I kill the process, will the shutdownhook still be executed before the process is killed?
Depends on how you kill it, but typically, yes, the shutdown hooks will be executed.

Java program not existing cleanly. Creates Zombies

SCENARIO
I have a java application (uses Spring Integration for Listening on TCP/IP port).
I am using a few worker threads with an ExecuterService created with java.util.concurrent.Executors factory.
The main thread creates the worker threads and waits in a loop like follows
while(!shutdownRequested)
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I have a shutdown hook which stops the executer service and forces shutdown in case of timeout.
PROBLEM
This program does not terminate successfully on my machine (Windows 7). It leaves one thread listening on the tcp port and the process becomes inaccessible after that.
I cannot kill this process from task manager and get an "access denied" error.
It is interesting that this problem happens only my machine and does not affect any other windows 7 machines. On all other machines Control-C from console always stops the program successfully.
I have faced this problem in the past (with the same application) and the problem magically disappeared after I re-formatted and re-installed windows. (i know this was a bit too much!!)
The application worked perfectly for many months untill unfortunately i had to re-format my computer again recently for other reasons. After the re-formatting the problem has come back again.
This is very frustrating as I have to re-start windows every time I need to re-start this application as it cannot bind to the TCP port becuase of the zombie process litening on that port.
Any ideas what could be wrong with my setup?
You probably need to close() the socket.
This will cause the socket to throw a SocketException, and therefore stop blocking.

How to kill a child process spawned by Java when tomcat is shutdown

I have written a service for JIRA(a web application runs in tomcat) which runs periodically(say 1 hour). Basically, the service executes a system command thru runtime.exec(command) and parses the output generated by the command then updates a Lucene index with it, output will be huge.
The problems are:
1) If I shutdown tomcat with shutdown.sh while the above service is executing, the java(or the catalina) process is not getting killed. Both the java & child process are living for a while i.e., until the system command completes & service processes the output. But then the service fails to update the index leaving the index in an inconsistent state.
If I shutdown tomcat when the above service is not running, everything is good. I think, this is explained here. I am still not clear why JVM won't shutdown as the above service is running within tomcat?
Note that this is the only java app running on that machine.
2) Then, if I kill java using kill <pid>, both the java & child process are getting killed contradicting to this post.
Is this because the child process is sending output to parent(java) and once parent is killed, the child has no idea where to send the output and thus got killed ?
3) I tried to use shutdownhook as explained in this post, but that's not working for me. The code inside the shutdownhook is getting executed only after the java & child processes are done with their work. So, calling process.destroy() inside shutdownhook is not useful here.
This seems obvious, as the JVM is still running in my case, it won't call shutdownhooks until it starts it's shutdown sequence. Don't know how this worked for the other guy, I mean, how come the child process spawned by java is still running when JVM is down.
4) If I restart tomcat, new java process with different pid is generated.
Is it possible to stop the child process programmatically when tomcat is shutdown ?
Let me know if I am not clear with my explanation...
Here is the code that executes system command:
String command = getCommand();
File view = new File(viewPath);
Runtime runtime = Runtime.getRuntime();
try
{
final Process process = runtime.exec(command, null, view);
StreamReader errorStreamReader = new StreamReader(process
.getErrorStream());
Thread errorStreamThread = new Thread(errorStreamReader);
errorStreamThread.start();
revisions = parseRevisionLogs(process.getInputStream());
process.waitFor();
process.getInputStream().close();
process.getErrorStream().close();
process.getOutputStream().close();
}
The JVM will not shutdown unless the threads that are left are marked as "daemon". Any non-daemon user threads must finish before the JVM will exit. See this question. If your periodic tasks are not set with setDaemon(true) then they will have to finish before the JVM will exit. You have to call setDaemon before the process starts.
You should be able to make your periodic tasks to be daemon however you do have a race condition with JVM shutdown. You might consider having one daemon task doing the reading from the process but having a non-daemon task do the updating of the index which probably should not get killed while it is working.
Your non-daemon thread could then be sleeping, waiting for the load to finish, and testing to see if it should terminate with a volatile boolean field or other signal.
I'd suggest you to do the following.
Do not read the process' output directly from java. Instead redirect the output to file and read it from there when process is terminated. Wrap your command using batch file or shell script that stores the PID of separate process, so that you will be able to kill this process separately. Now add shutdown hook to tomcat that will run kill PID where PID is the process ID of separate process.
I believe this will work because now your tomcat and separate process are totally decoupled, so nothing bothers tomcat to shutdown. The same is about the process.
Good luck.
Are you doing a waitFor() on the process?
If so you could catch InterruptedException and to a p.destroy()

Categories