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();
}
}
}
}
Related
I have a java-program which runs on a schedule and fetches some data from external sources via RFC calls. The RFC calls are threaded and shall be canceled after 60 seconds. This is how I do it:
Future<String> future = executor.submit(new MyCallable());
try {
future.get(60, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
}
This worked for a long time until I came accross a situation, where the external RFC call became stuck and future.cancel(true) was unable to interrupt the thread-execution. So my java-program never finished and continued running until I manually canceled the corresponding process within the external system.
My question now is, how can one guarantee the code to finish in any situation? I saw that stopping the thread is depreciated.
Would it be a good idea to do sth like this?
try {
future.get(60, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
if(!future.isDone()){
System.exit(1);
}
}
Thanks for any ideas on this.
Cheers, Jooo
I believe that there's no way in Java to just kill off a thread if during execution not implemented InterruptedException . If the thread is executing, it just sets a flag and it's up to the thread to notice it. if the thread is waiting or sleeping, it will throw an InterruptedException.
No need to check after every line, of course, but methods which can take a long time to execute are responsible for properly handling interrupts
kill the process in which the thread is running. (E.g., call System.exit(int).)
I currently have the following problem:
I have made a 'Cache Updater Thread', which checks for updates and then sleeps for some amount of time. I have also build a Button, which enables the user to check for updates manually. The Thread is built like this:
public static Thread cacheUpdater = new Thread(new Runnable() {
int milliSecondSleepTime = 10000;
public void run() {
try {
cacheUpdater.setPriority(Thread.MIN_PRIORITY);
//Infinite loop
while (!terminate) {
syncStatus.set(0);
//Check for updates with some methods, not important here.
syncStatus.set(1);
Thread.sleep(this.milliSecondSleepTime);
}
}
catch (InterruptedException e) {
//First check if it is termination time
if (!terminate) {
syncStatus.set(0);
this.run();
}
}
catch (Exception e) {
System.out.println(e);
}
return;
}
});
If the user clicks the manual-update button, the following code is being runned:
#FXML public void syncOnRequest() {
//Only call interrupt, because then it will start again when terminate is still false
CacheManager.cacheUpdater.interrupt();
System.out.println(CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING));
while (!CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING)) {
//LOOP FOREVER
}
//Some code that needs to be executed after the cache is updated
}
I would like to continue executing code in the syncOnRequest() method, when the cache updater is ready with its manual update. I had the idea to check if it is sleeping, but this is not working, because the System.out.println() immediately returns true. I have measured the time it takes to do the update, and its between 200 and 400 ms.
What am I doing wrong here? And why is it always returning true?
Additional question: sometimes a click on the button just kills the Thread, because it just woke up. The InterruptedException is not thrown.
How can I make sure the Thread will also restart in that case?
Note that Thread#interrupt() is the only polite way to ask your thread to interrupt itself (unless you explicitly implement another). Using it to restart the check is therefore a bad practice. So is checking the thread state for synchronization purposes and exposing the thread that keeps your cache up-to-date to external clients.
You manager should have a updateCache() method you will call directly from UI code and auto-update thread will call the same method periodically*. In that method, make sure that access to your cached data is either correctly synchronized or it happens atomically.
*) Instead of implementing your own periodic thread, consider using
Timer and TimerTask classes as well as making it a daemon thread.
In my app I got some activities and a ReceiverThread.class.
The Thread is started from two different activities. And everytime I switch to another Activity and recall the former active Activity it starts a new Thread. So if I do some test on my app for about 10 Minutes or the app is simply used for some time, there is a mass of Threads open and all do the same.
Most of the time the Threads are on TimedWait.
This gives me wrong data and causes the app to lag hard, sometimes its not even responding.
Is there a good possibility to stop a thread onPause() or onStop() ? Because many of the methods are deprecated. Or how to resume a previous started Thread and so prevent the Activity from creating a new one?
This is my ReceiverThread.run():
public void run() {
initiateCAN();
while (true) {
try {
Thread.sleep(60);
mHandler.post(r);
} catch (InterruptedException e) {
break;
}
}
}
If something is not clear or missing, please feel free to ask and I will edit my post, but don't just simply downvote.
The recommended way to do this is to use the built-in interrupt system. You can then stop the thread by calling Thread.interrupt() (best in onPause() if you don't want multiple instances). Your run method would need to be somewhat changed:
public void run() {
initiateCAN();
try {
while (!isInterrupted()) {
Thread.sleep(60);
mHandler.post(r);
}
} catch (InterruptedException e) {
}
}
While this might work, it's still better to use a Service or another way to make sure there is only one instance at one time (maybe fragments instead of activities?).
You can use Android Services, and that service starts the thread. When you switch the activity, the services is running and not is necessary start a new thread.
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.
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.