When I use 4 threads for my program there is usually no problems, but today I increased it to 8 and I noticed 1-3 threads stop working without throwing any exceptions. Is there anyway to find out why they are stopping? is there anyway to make the thread restart?
This is how the structure of my thread is
public void run()
{
Main.logger.info(threadName + ": New Thread started (inside run)");
while (true)
{
try
{
//all my code
//all my code
//all my code
}
catch(Exception e)
{
Main.logger.error("Exception: " + e);
try
{
Thread.sleep(10000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
finally
{
try
{
webClient.closeAllWindows();
Thread.sleep(3000);
Main.logger.info(threadName + ": Closed browser!");
}
catch (Exception e)
{
Main.logger.error("Exception: " + e);
}
}
}// end while
}
Regards!
Note that an Error is not an Exception; it's a Throwable.
So, if you catch Exception, Errors will still get through:
private void m() {
try {
m(); // recursively calling m() will throw a StackOverflowError
} catch (Exception e) {
// this block won't get executed,
// because StackOverflowError is not an Exception!
}
}
to catch "everything", change your code to this:
try {
...
} catch (Throwable e) {
// this block will execute when anything "bad" happens
}
Note that there might be little you can do if an Error occurs. Excerpt from javadoc for Error:
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
Is there anyway to find out why they are stopping?
That's a bit tricky.
A Java thread can terminate for two reasons:
it can return from its run() method,
it can terminate due to an exception being thrown and not caught on the thread's stack.
You can detect the latter case by using an "UncaughtExceptionHandler" for the thread, but the former case can't be positively detected unless you modify your thread's run() method to log the event ... or something like that.
I guess, the other way to figure out what is going on would be to attach a debugger to the JVM and get it to report the uncaught exception to you.
(I suspect that the reason you are not seeing any exceptions is that your threads' run methods are not catching / logging all exceptions, AND they don't have an uncaught exception handler.)
is there anyway to make the thread restart?
No. There is no way to restart a Thread that has terminated.
If you are running from the command line, you can have dump states of all threads to the console. On windows you do this by hitting Ctrl+Break, under linux, by sending the QUIT signal to the process with 'kill'.
Please refer to An Introduction to Java Stack Traces
Sending a signal to the Java Virtual Machine On UNIX platforms you can
send a signal to a program by using the kill command. This is the quit
signal, which is handled by the JVM. For example, on Solaris you can
use the command kill -QUIT process_id, where process_id is the process
number of your Java program.
Alternatively you can enter the key sequence \ in the window
where the Java program was started. Sending this signal instructs a
signal handler in the JVM, to recursively print out all the
information on the threads and monitors inside the JVM.
To generate a stack trace on Windows 95, or Windows NT platforms,
enter the key sequence in the window where the Java
program is running, or click the Close button on the window.
Thread priority on one of them could be too high, try setting them the same level through?
Deadlocking is possible if there is any control on each and other between them.
Related
I have a Docker container with a Java application that uses a DB to persist some data. My application has a class that extends another one that is not code of mine (specifically SinkTask, a class from Kafka that is used to transfer data from Kafka to another system). When the application starts it opens a connection to the database. Sometimes, the database closes the connection and tasks start to fail. The exceptions thrown by these failures are catched in one part of my code and I can think of different ways to handle them:
1. Simply executing the code from within the application that stops and starts the connection again
2. Restarting the Docker container, creating a new connection in the process
I think the best solution is number 1. However, I wanted to know how could I trigger the second situation. My guess is that I should throw a new Exception in the catch block capable of terminating the application (remember that the SinkTask part of the code is out of my control). Would this be a good solution? Which kind of Exception should I throw in this case?
This is the part of the code where I catch the exception
private void commitCollections() {
for (SinkCollection sc : collections.values()) {
try {
commitCollection(sc);
} catch (Exception e) {
LOG.error("Error flushing collection " + sc.getTableName(), e);
}
}
transactionRecordCount = 0;
try {
connection.commit();
} catch (SQLException e) {
LOG.error("Commit error", e);
}
}
Throwing an Exception and letting it propagate in order to terminate the application is a perfectly nice solution. IMO, using System.exit(exit_code) would be better because it clearly describes what that code is doing.
In addition, docker will display the exit_code in the status of the container (docker ps -a), thus helping differentiate between different error conditions. When an uncaught exception is thrown the exit code is always 1.
Hope that helps.
Let's say I have a thread (Critical) running. Let's say I have another thread (WatchDog) in the same process that periodically checks if Critical is processing jobs quick enough or if it has spent > X seconds on 1 job. If Critical is spends > X seconds on 1 job, then WatchDog grabs the call stack of Critical, some other diagnostic information and reports a bug. (One place I use this is to detect if the Swing UI thread hangs. I use this in other performance sensitive places in code.)
If I attach a debugger (e.g. Eclipse), set a breakpoint and Critical hits the breakpoint, then WatchDog will report a bug because Critical takes too long. How can I make WatchDog detect that Critical hit a breakpoint and not report a bug?
Currently, I simply disable WatchDog when running on a development machine; otherwise, I will get a lot of bug reports (errors logged to the console on development machine). If I simply detect that a debugger is attached, then WatchDog will almost always end up disabled since that is how I run the program. So, detecting an attached debugger is not sufficient.
I could set a breakpoint in WatchDog right before it reports a bug. I could then allow WatchDog to resume if it detected an actual bug. This is okay but I am looking for something a little more automated.
The JVM knows that the thread hit a breakpoint. How do I inspect this state?
Note: This question is the same but for .Net.
From what I know you can't receive debug information unless you are registered to received receive Debug events from the JVM, so you might have to write your own agent.
Failing that, this is a little hacky, but as mentioned in the .NET question, if you are using Eclipse, you can use a condition on the breakpoint at Critical to set a System property, "com.acme.critical-stopped" or something when the breakpoint is hit.[]
Then, the WatchDog thread can check the system property to see if it is set before filing a bug.
On the line after the breakpoint you would need to set a second conditional breakpoint. This condition will always return false so the Critical thread won't stop again, it will just change the system property back to false.
Try the code below with the breakpoints set where indicated and it works for me.
public class T1 {
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
int i = 0;
while (i < 1000){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Stopping");
System.out.println("Finished");
}
}
}, "WatchDog").start();
while (true){
System.out.println("Stopped ? " + System.getProperty("IsStopped"));
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Say I have the following code:
try {
//Do something with File
} catch (FileNotFoundException e) {
outputInfo("Error in IO Redirection", true);
e.printStackTrace();
System.exit(1);
}
My program exits right after this catch location, is a single thread (one main method) program and should not expect to recover from such an exception.
Should I really be using System.exit(1); ?
If you expect someone else to run your program, and they rely on the process status code to know if your program has succeeded or failed, then you should use System.exit(1);
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#exit%28int%29
Terminates the currently running Java Virtual Machine. The argument
serves as a status code; by convention, a nonzero status code
indicates abnormal termination.
One of the reasons to use a non zero exit code on failure of an application is that they can be used in batch files. If your application is a console application always use proper exit code. You don't know how it will be used in future.
I suspect an exception could make the TimerTask stop running in which case I most likely need a second timetask to monitor that the first is still running?
Update
Thanks for the answers. I had inherited this code so a bit ignorant...
I just saw that if I throw an uncaught exception in my job the TimerThread ceases to run forever.
Run method of TimerThread showed that if an exception is thrown, my scheduled thread never runs again.
public void run() {
try {
mainLoop();
} finally {
// Someone killed this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsolete references
}
}
}
The end of the stacktrace will be:
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
So temp solution is to catch EVERYTHING... longer term solution is to move to better scheduling as BalusC states.
TimerTasks die when an uncaught exception is thrown (whether it's running in tomcat or not is unrelated). The easiest way to resolve this is to catch RuntimeException in your run method, and log & continue if that's what you want.
It's also advisable to catch Throwables as well and log it before you rethrow it so that you can see the stacktrace in your logs, like this:
try{
doRun();
}catch (RuntimeException e){
logger.error("Uncaught Runtime Exception",e);
return; // Keep working
}catch (Throwable e){
logger.error("Unrecoverable error",e);
throw e;
}
Runtime.getRuntime.exex("abc.exe -parameters");
using .waitFor() does not help to determine the completion of process.
Looks like JDK8 introduces Process.isAlive(). Surprised it took so long...
In the meantime, the best option seems to be to poll Process.exitValue(), wrapped in a try-catch:
// somewhere previous...
String[] cmd = { "abc.exe", "-p1", "-p2" };
Process process = Runtime.getRuntime.exec(cmd);
// call this method repeatedly until it returns true
private boolean processIsTerminated () {
try {
process.exitValue();
} catch (IllegalThreadStateException itse) {
return false;
}
return true;
}
Alternately, a similar method could return the exit value if the process had terminated, or some other specified value if not.
Process.waitFor() (javadoc) should work. If it doesn't work then either:
there's a bug in the JVM or the OS (highly unlikely for something like this), or
there is something about the process and/or your Java code that means that the process won't exit.
In current releases of Java you can also use Process.isAlive (javadoc) to test the process status without blocking until it finishes. For Java 7 and older there is a hacky solution that entails polling the process return code and catching an exception, but this is inefficient. You should upgrade to Java 8 or later as soon as possible!
Once the task is finished its goes for an indefinite wait. (I don't know why).
If this happening, then neither waitFor() or isAlive() will help.
The most likely reasons that a process launched from Java won't / can't exit are:
the process is blocked waiting for your Java application to give it some input (via its stdin),
the process is blocked waiting for your Java application to read its output (i.e. its stdout or stderr),
it is blocked waiting on some external event; e.g. if it is trying to talk remote server that is not responding,
something has sent it a STOP signal of some kind, or
it is just taking a looong time to run.
The first two of these reasons / causes can be addressed by (respectively) closing the Java output stream connected to its standard input, and reading (and possibly discarding) the Java input streams connected to its standard output and standard error. The other causes are intractable, and your only options are to "wait it out" or attempt to kill off the process.
Bottom line - you need to find out why your process isn't completing. The blocked Process.waitFor() call is a symptom, not the disease.
I have a similar issue and neither of the methods written here works for me. This is my code:
public void startCCleaner() {
System.out.println("Starting ccleaner...");
try {
Process process = new ProcessBuilder("C:\\Program Files\\CCleaner\\CCleaner64.exe").start();
if(process.waitFor() == 0 ){
System.out.println("Process terminated ");
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
If you don't want to use waitFor(), which apparently you don't you can always test the exit value directly.
import java.util.*;
import java.io.*;
public class ProcExitTest
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("<....>");
int exitVal = proc.exitValue();
System.out.println("Process exitValue: " + exitVal);
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
}
}
exit code 0 means normal termination.