Java try finally variations - java

This question nags me for a while but I did not found complete answer to it yet (e.g. this one is for C# Initializing disposable resources outside or inside try/finally).
Consider two following Java code fragments:
Closeable in = new FileInputStream("data.txt");
try {
doSomething(in);
} finally {
in.close();
}
and second variation
Closeable in = null;
try {
in = new FileInputStream("data.txt");
doSomething(in);
} finally {
if (null != in) in.close();
}
The part that worries me is that the thread might be somewhat interrupted between the moment resource is acquired (e.g. file is opened) but resulting value is not assigned to respective local variable. Is there any other scenarios the thread might be interrupted in the point above other than:
InterruptedException (e.g. via Thread#interrupt()) or OutOfMemoryError exception is thrown
JVM exits (e.g. via kill, System.exit())
Hardware fail (or bug in JVM for complete list :)
I have read that second approach is somewhat more "idiomatic" but IMO in the scenario above there's no difference and in all other scenarios they are equal.
So the question:
What are the differences between the two? Which should I prefer if I do concerned about freeing resources (especially in heavily multi-threading applications)? Why?
I would appreciate if anyone points me to parts of Java/JVM specs that support the answers.

I don't think there is any reason to be concerned:
1) InterruptedException (e.g. via Thread#interrupt())
Calling Thread.interrupt() does not cause InterruptedException to be thrown spontaneously. The exception is only thrown within specific (and well documented) blocking methods; i.e. blocking I/O and synchronization methods. This exception cannot be thrown after returning from the stream constructor and before entering the try block.
or OutOfMemoryError exception is thrown
If an OutOfMemoryError is thrown, you cannot guarantee full recovery of the underlying file descriptor, no matter where you put the stream constructor. You should never attempt to recover from an OOM, so the question of whether the stream is closed is moot. Besides, this exception is only thrown on a thread that is actually attempting to allocate memory, and that is not happening at this point.
2) JVM exits (e.g. via kill, System.exit())
If the application is being forcibly terminated by an external kill or a System.exit() call, it does not matter if streams are closed properly. Besides, in both cases there is no guarantee that finally clauses will be executed.
3) Hardware fail (or bug in JVM for complete list :)
All bets are off. You have no way of knowing if anything will execute, let alone the finally blocks.
There is one more situation where a thread might receive an spontaneous exception at that point, with some (naive) expectation that it might recover. That is when some misguided programmer decides to call the deprecated Thread.stop() method. You might think that putting the stream constructor call inside the try block would help. But actually it won't, because the ThreadDeath exception could be raised inside the stream constructor between opening the underlying file and completing construction of the stream object. So the FD could leak anyway.
This is just one reason why Thread.stop() is deprecated. Don't use it.

a) Note that interrupting the thread with interrupt() will not take effect immediately, and may not have any effect at all, if the thread being interrupted does not cooperate. There is no way the thread will exit due to interrupt() during the execution of :
Closeable in = new FileInputStream("data.txt");
The only thing that will happen is that its interrupted flag of the thread will be turned on.
b) regarding OutOfMemoryError - I don't see how it can occur right after the construction of the input stream. It may occur in another thread, but this will have no immediate effect on this thread. The problem with OutOfMemoryError, is that your finally block may also fail, because there is not enough memory to complete it...
c) The only way I know that a thread can be interrupted aggressively is using the deprecated methods Thread.stop() and Thread.stop(Throwable).
See a similar discussion here:
Is this a safe way to release resources in Java?

My view is that is when you are working with a managed runtime, such as Java or .NET you really should not (and it's good!) concern yourself with things like your particular question. Only because you are completely disconnected from the underlying operating system and its native APIs. All you have to know is that you call Closable.close() in your finally block and your resource will always be freed.

Related

Reliably stopping an unresponsive thread

I'm wondering how to stop an unresponsive thread in Java, such that it's really dead.
First of all, I'm well aware of Thread.stop() being deprecated and why it should not be used; there are already many excellent answers on this topic, cf. [1][2]. So, the question more precisely is, whether it's actually technically possibly to kill a thread which code is not controlled by us but possibly hostile and not responding to interrupts.
In the simplest case, a hostile thread would be running while(true);, but it could as well be using up memory or other system resources to do more damage. Calling interrupt() on that thread is obviously ineffective. What about calling stop() instead?
I have run this in a debugger and, in fact, the thread really disappears. But is this approach reliable? The hostile thread could be prepared for this case; think of try{run();}catch(ThreadDeath t){run();} where it catches the ThreadDeath that is produced when we call stop() and recursively calls itself again.
As an outside observer, we cannot see what is going on; Thread.stop() always runs silently. Worst of all, the usual diagnostics won't work anymore (tried this while debugging on Corretto 1.8.0_275 Windows x64): Thread.getState() always returns RUNNABLE regardless of success in killing the thread, same goes for Thread.isAlive() (always true).
It may not be possible, at least not reliably in every scenario.
IF I understand the mechanism correctly (and there is some uncertainty there), if the code executes in such a way that there are no safepoints during the execution (for example in counted loops), it is not possible for the JVM to signal to the thread that it should stop (the thread never polls for an interrupt).
In such a scenario, you need to kill the JVM process, rather than the thread.
Some extra reading:
How to get Java stacks when JVM can't reach a safepoint
Counted loops
In a nutshell, there's no 100% reliable way to stop a Thread the way you'd like it.
Why?
This is an explanation for others who don't know why, anyone who knows the issue can skip this.
The way how threads are intended to be terminated forcefully is with the interruption state of the Thread. A Thread should be terminated with its interrupt() method is called which sets a boolean flag to true.
When the interruption flag is set to true, the Thread should terminate itself with virtually no delay.
Anyway the Thread can choose to simply ignore this and keep on running.
This is when the stop() method can be called that forces the Thread to terminate. The problem is that this method messes up concurrency, can damage objects and the program can be corrupted without a warning for the user. See Why the stop() method is deprecated?
At the end I could think of two possible ways, one is basically your way, the other one is safer but more complicated.
As an example, a hostile third party .jar which contains a Thread that refuses to terminate can cause these problems.
Quick & Dirty
This solution isn't completely safe but based on the usage this may be acceptable unless you really like security.
Try to first to call the interrupt() method on the Thread and give it a bit time to terminate.
If the Thread doesn't respond, you can either:
terminate the program and warn the user to not run that Thread again.
stop() the thread and hope for the best.
Complicated & Safe
The safest solution I can think of is creating a whole new process to run the Thread in. If the Thread doesn't want to terminate after interrupt(), you can just end the process with System.exit(-1) and let the OS handle it.
You need Inter Process Communication to communicate with the other process and that makes it a lot more complicated but also safer.
Related
How do you kill a Thread in Java?
What is an InterruptedException in Java? (Disclaimer: I've answered it)
What does java.lang.Thread.interrupt() do?
For me isAlive returns false if the process finishes due to Thread.stop.
I've made the following example, and it successfully kills the errant thread.
import java.util.Arrays;
public class BrokenThreads{
static boolean[] v = { true };
public static void call(){
try{
while(true){
Thread.sleep(200);
}
} catch ( Throwable td){
System.out.println("restarting");
call();
}
}
public static void main(String[] args) throws Exception{
Thread a = new Thread( BrokenThreads::call);
a.start();
Thread.sleep(500);
System.out.println( Arrays.toString( a.getStackTrace() ) );
while(v[0]){
a.stop();
System.out.println(a.getStackTrace().length);
v[0] = a.isAlive();
}
System.out.println("finished normally");
System.out.println( Arrays.toString( a.getStackTrace() ) );
}
}
Note that "getStackTrace" takes time, and you can see the stacktrace accumulate as recursive calls are made, until two stops happen quick enough to end the thread.
This uses two techniques to see if the thread has stopped. isAlive and the depth of the stack trace.
I think the question describes a scenario that is the reason why Thread.stop() is deprecated since ages now, but was not yet removed … just to have a 'last resort option', to be used only when being really desperate and being aware of all the negative impact.
But that call to Thread.stop() must be build into the code somehow, same as any alternative one may think about – so why not just fix the code for the thread? Or, if that is not possible because that code comes with a third party library without source code, why not replacing that library instead?
Ok, during testing, your own code may go wild, and you need an emergency break – for that, Thread.stop() is still good enough if you do not want to kill the whole JVM (what would be the better option in most of the cases). But again, you have to build this into the code before you start the test …
But in production, there should never be a thread that does not stop when receiving an interrupt. So there should be no need for a replacement of Thread.stop().
This can potentially open a can of worms like memory access violations which will kill the JVM itelf.
What you could do is isolate the thread, running .finalize() on it, then forcing the JVM to run GC operations such as Runtime.gc(), System.runFinalization() while forcing interruptions on that particular thread in order to bypass it's resurrection behavior.
I think .finalize() is effectively deprecated since java11 or maybe sooner, so it probably won't help you much.
If you really want to secure your runtime during it's operational cycles, your best bet would be to find a way to essentially map out your configuration before you start it, and have monitoring tools set up which cross-check against that map and monitor the integrity of your runtime while looking for injected classes and/or threads. ... this is assuming of course, you're attempting to guard against "virus-like" attacks in your jvm ... which is not exactly unheard of but still pretty rare.
If you're running some code off the internet, you could simply solve the issue with a call hierarchy inspection and figure out what spawns that problematic thread.
Note: If that invasive thread is calling native dll code which is looping back into it's caller, then your JVM will crash if you mark sections of it's address space as garbage collected.

Java - concurrency: LinkedBlockingQueue, "try again if failed"

int capacity = ...
BlockingQueue q = new LinkedBlockingQueue<Element>(capacity);
Now, I do feel mildly ridiculous asking this but I'm not particularly savvy when it comes to java concurrency, so I would appreciate some help with choosing the correct way to enqueue something (and dequeue, actually, but I expect when we cleared up the one, the other will fall into place by itself).
There is, of course
while(!q.offer(e));
But I'm a bit wary of spinning implementations in a multi-threaded environment.
And I can't do
synchronized(q){
while(!q.offer(e))q.wait();
}
either because the wakeup calls will go to internal (private) instances of Condition, meaning this would be a suicide-by-sleeping-pills implementation.
However, I'm also not particularly fond of
try{
q.put(e);
}catch(InterruptedException ex){}
(even though it does seem to be a popular choice in online examples) because although this would do the waiting for me, I know of no reliable way to detect when an exception would force me to try again.
I could do something like
boolean success = false;
do{
try{
q.put(e);
success = true;
}catch(InterruptedException ex){}
}while(!success)
But then I'd end up enqueuing the same element multiple times if the exception takes place in-between the put and the assignment to success.
I could do
boolean success = true;
do{
try{
q.put(e);
}catch(InterruptedException ex){
success = false;
}
}while(!success)
But I remember having read (way back) that you shouldn't rely on exception handling for conditionals (though I can't seem to remember the reason why this is discouraged).
So ... what options do I have? Do I need to spin or is there something more intelligent?
It is not a good practice to catch an InterruptedException as you do since your code won't be responsive to interruption anymore. An InterruptedException is usually thrown by methods that are responsive to interruptions (current Thread being interrupted) such as the methods of type await, wait, join, sleep and many others, this should not be considered as a failure but rather as it really is, a Thread's status change that needs be taken into consideration.
As Brian Goetz explains in Java Concurrency in Practice, I quote:
When your code calls a method that throws InterruptedException, then
your method is a blocking method too, and must have a plan for
responding to interruption. For library code, there are basically two
choices:
Propagate the InterruptedException. This is often the most sensible policy if you can get away with it just propagate the
InterruptedException to your caller. This could involve not catching
InterruptedException, or catching it and throwing it again after
performing some brief activity-specific cleanup.
Restore the interrupt. Sometimes you cannot throw InterruptedException, for instance when your code is part of a
Runnable. In these situations, you must catch InterruptedException
and restore the interrupted status by calling interrupt on the
current thread, so that code higher up the call stack can see that an
interrupt was issued.
So in your case, you should simply use put(E) as it will make the calling thread waits for space to become available if needed and propagate the InterruptedException in order to keep on being responsive to interruptions.
But then I'd end up enqueuing the same element multiple times if the
exception takes place in-between the put and the assignment to
success.
This can simply never happen since an assignment of a boolean will never throw any exceptions (except a NPE in case of an un-boxing). And only methods responsive to interruption can throw such kind of exceptions as explained above which is clearly not the case of an assignment.
The put() implementation would be the correct one, blocking until interrupted or successful. The offer() is a bad idea if all you are doing is spinning (see first comment for disclaimer).
As Nicolas explained, the handling of the InterruptedException is not straightforward and depends a lot on what your other code is doing, but your concern with "if the exception takes place in-between the put and the assignment to success", that can never happen: a blocking call (like put()) can throw that exception, but it cannot occur between put() and the assignment, or at the assignment.
Lastly, there's no need to synchronize on anything. The main idea in many of java.util.concurrent classes is to avoid or abstract away the explicit synchronization.
So a few points from the LinkedBlockingQueue Javadoc:
The put method will only throw exceptions in two circumstances:
The thread is interrupted, in which case you should stop whatever you're doing anyway. See this question for more about InterruptedExceptions.
The element you're inserting is null, which is another bug entirely.
So overall, you can just use put to wait for space to become available. If either of these particular exceptions is thrown, then you shouldn't retry anyway.

How Java thread.stop() work?

I am actually looking for an easier way to kill the thread not matter where the thread is running at. But most of the solutions in internet point me to use boolean flag to control the execution of the thread, if I want to stop the thread then set the boolean variable to false.
But what if the task that in the runnable is a LONG linear task, which mean the task is not repeating? In that case, it is not so easy to create a 'while' loop to cover the whole block of task.
It is really so temptative to use Thread.stop but the warning "Deprecated" seem like quite dangerous to use. I have read through this article
Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?
but I can't understand
If any of the objects previously protected by these monitors were in
an inconsistent state, other threads may now view these objects in an
inconsistent state. Such objects are said to be damaged.
What does the "inconsistent state" mean? I appreciate if anyone can explain about this.
I want to extend my question to a more lower level of view, let say i = i + 1; in JVM (perhaps assembly language alike), maybe this Java statement will be split into few smaller instructions, for example like move i ; add i ; get i into memory 0x0101 (This is an example! I totally don't know assembly language!)
Now, if we call thread.stop, where actually will it stop at? Will the thread stop after a COMPLETED Java statement, or could be in the middle of the "assemble language"? If the answer is the second, could it be reason that we said
Such objects are said to be damaged.
?
Ok, my question is kind of confused, hope someone can understand and explain. Thanks in advance.
"Damaged object" is a high-level concept, it doesn't happen at the JVM level. A programmer designs his class with thread safety in mind by guarding critical sections with locks. It is an invariant of his class that each critical section either runs in full, or doesn't run at all. When you stop a thread, a critical section may have been interrupted in the middle, so disrupting the invariant. At that moment the object is damaged.
Stopping a thread conceals many more dangers, like no cleanup performed, no acquired resources released, etc. If a thread doesn't give up what it is doing, there is no way to make it stop without compromising the entire application.
In practice, whenever one faces the need to run alien code that may need to be forcefully aborted, this must be done in a separate process because killing a process at least performs OS-level cleanup and does a much better job of containing the damage.
The "inconsistent state" means state of data as your application cares about, state that your application logic have carefully produced by making your application thread-safe with locks/monitors etc.
Imagine you have this simple method:
public synchronized void doSomething()
{
count++;
average = count/total;
}
This method, along with other methods are synchronized, as multiple threads are using this object.
Perhaps there's a
public synchronized AverageAndCount getMeasurement()
{
return new AverageAndCount(average, count);
}
This assures that a thread can't read an incomplete measurement, i.e. if the current measurement is in the process of being calculated inside e.g. doSomething(), getMeasurement() will block/wait until that's finished.
Now, imagine the doSomething is run in a thread, and you call .stop() on that thread.
So the thread might be stopped right after it performs count++;, the monitor that's held is unlocked and the method terminates and average = count/total; is not executed,
That means the data is now inconsistent. Anyone calling getMeasurement() afterwards will now get inconsistent data.
Note also that at this point it is not very relevant whether this happens at a java statement level, or at a lower level, the data can be in an inconsistent state that you can't reason about in any case.
I'm no expert but this is what I think.
If you use Thread.stop() you cause the ThreadDeath exception that will cause all monitors to be released.
Since you provoke an exception you are applying an unnatural behaviour to the state of things.
Other threads relying on those monitors could enter in an inconsistent situation because they were not expecting it. And I don't think you can even anticipate the monitors releasing order.
I believe the concern is that the thread may be in the middle of a synchronize block performing multi-step updates to an object's members. If the thread is stopped abruptly, then some updates will have occurred but not others and now the object's state may render it unusable.
I have my doubts that the ThreadDeath handling will release a Lock backed by the AbstractQueuedSynchronizer which could leave the application on the path to a sort of deadlock.
At any logical point in your long sequence of code you can simply add:
if (Thread.interrupted()) {
throw new InterruptedException();
}
...this will exit execution at this point if it is determined that Thread.interupt() was called on the Thread executing the long running task.
It's not clear way to stop the thread.actually deprecated the stop() method whenever run() method is completed or any exception is occurred then thread is stop.by using the boolean flag variable .Bydefault "false"

Java breaking an infinite loop

I have particular situation in our production environment, where a particular piece of code goes into an infinite loop. The cause is mostly data specific and not able to figure out the true cause. In the mean time, what I am hoping to do is spawn a separate child thread to execute that piece of code, and if it executes for say more than 30s, want to stop that child thread from executing
Thread t = new Thread() {
public void run() {
// This is where i will the method that runs in a infinite loop
callMethodThatRunsInInfiniteLoop();
};
};
t.start();
try {
t.join(2000); // wait 2s
} catch (InterruptedException e) {
e.printStackTrace();
}
// if not completed how to break the child thread ???
unfortunately no it is a thirdparty code, and will not be able to change it so easily.
It sounds like you are trying to work around a problem in the third-party library ... or in your code calling the third-party library with bad input or something.
My advice would be to fix THAT problem, rather than trying to kill the errant thread(s). And if you can't do that, then you have two choices:
modify the 3rd party library to be interrupt aware/responsive, and then use that to stop it, or
try to find a way to "reach into" the 3rd party library's data structures (e.g. using nasty reflection) and cause it to die.
If you are resorting to the latter, then maybe you should also look at running the 3rd party library in a separate JVM so that you can forcibly kill it using the Process API.
Having said that, there are limited circumstances where Thread.stop() is actually (probably) safe to use. Basically, if the errant thread doesn't create child threads, doesn't interact with other threads and doesn't share data structures, and can't be doing class initialization when you kill it, then you are probably going to be safe. The problem is there are so many theoretical scenarios where stopping the thread could cause damage that it is hard to know that you've considered all of them.
Is there a way to cause the infinite loop code to break by throwing an exception? e.g. set some variable to
null? A possible advantage is that the affected thread (if well written) will clean up after itself and shut down more nicely than a stop().
All methods for stopping a thread 'purely externally' are deprecated and considered unsafe. The only way a thread can be safely stopped requires
modifying the code which is running to check whether it has been politely asked to stop via some stopMe variable being set; or
co-opting a variable the other thread already uses to cause the thread to quit (which is generally very bad practice); for example, by forcing it to throw an exception, as suggested by user949300.
Without this, you have no choice but to use an unsafe method, which means Thread.stop(), which is also very bad practice. This is a very bad idea, and of course the only real solution is to either change your input so that this doesn't happen, or get the third-party code fixed.
Any objects the thread was using may be in an inconsistent (and possibly unusable) state, so try to avoid letting the Thread modify anything important, and don't look at any of its output variables if you can help it.
The Thread.stop() method still seems to exist in Java SE 7, though is of course deprecated, but I can't vouch for your particular environment.
See http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Depending on the implementation of the method, you could start it in its own JVM, then stop it by calling destroy() on the process:
Process process = new ProcessBuilder("java", "-cp", "/some/class/path", "com.mycompany.MyLauncher").start();
// sometime later
process.destroy();

Who is calling the Java Thread interrupt() method if I'm not?

I've read and re-read Java Concurrency in Practice, I've read several threads here on the subject, I've read the IBM article Dealing with InterruptedException and yet there's something I'm simply not grasping which I think can be broken down into two questions:
If I'm never ever interrupting other threads myself, what can trigger an InterruptedException?
If I'm never ever interrupting other threads myself using interrupt() (say because I'm using other means to cancel my working threads, like poison pills and while (!cancelled) style loop [as both explained in JCIP]), what does an InterruptedException then mean? What am I supposed to do upon catching one? Shutdown my app?
The Thread interrupt mechanism is the preferred way to get a (cooperating) thread to respond a request to stop what it is doing. Any thread (including the thread itself I think) could call interrupt() on a Thread.
In practice, the normal use-cases for interrupt() involve some kind of framework or manager telling some worker thread to stop what they are doing. If the worker thread is "interrupt aware" it will notice that it has been interrupted via an exception, or by periodically checking its interrupted flag. On noticing that it has been interrupted, a well-behaved thread would abandon what it is doing and end itself.
Assuming the above use-case, your code is likely to be interrupted if it is run within a Java framework or from some worker thread. And when it is interrupted, your code should abandon what it is doing and cause itself to end by the most appropriate means. Depending on how your code was called, this might be done by returning or by throwing some appropriate exception. But it probably should not call System.exit(). (Your application does not necessarily know why it was interrupted, and it certainly does not know if there are other threads that need to be interrupted by the framework.)
On the other hand, if your code is not designed to run under the control of some framework, you could argue that the InterruptedException is an unexpected exception; i.e. a bug. In that case, you should treat the exception as you would other bugs; e.g. wrap it in an unchecked exception, and catch and log it at the same point you deal with other unexpected unchecked exceptions. (Alternatively, your application could simply ignore the interrupt and continue doing what it was doing.)
1) If I'm never ever interrupting other threads myself, what can trigger an InterruptedException?
One example is if your Runnable objects are executed using an ExecutorService and shutdownNow() is called on the service. And in theory, any 3rd-party thread pool or thread management framework could legitimately do something like this.
2) If I'm never ever interrupting other threads myself using interrupt() ... what does an InterruptedException then mean? What am I supposed to do upon catching one? Shutdown my app?
You need analyze the codebase to figure out what is making the interrupt() calls and why. Once you have figured that out, you can work out what >>your<< part of the app needs to do.
Until you know why InterruptedException is being thrown, I would advise treating it as a hard error; e.g. print a stacktrace to the log file and shut down the app. (Obviously, that's not always the right answer ... but the point is that this is "a bug", and it needs to be brought to the attention of the developer / maintainer.)
3) How do I find out who / what is calling interrupt()?
There is no good answer to this. The best I can suggest is to set a breakpoint on the Thread.interrupt() and look at the call stack.
If you decide to integrate your code with other libraries, they can call interrupt() on your code. e.g. if you decide in the future to execute your code within an ExecutorService, then that may force a shutdown via interrupt().
To put it briefly, I would consider not just where your code is running now, but in what context it may run in the future. e.g. are you going to put it in a library ? A container ? How will other people use it ? Are you going to reuse it ?
As others have pointed out, interrupting a thread (actually, interrupting a blocking call) is usually used for purposes of exiting cleanly or cancelling an ongoing activity.
However, you should not treat an InterruptedException alone as a "quit command". Instead, you should think of interrupts as a means to control the running status of threads, much in the same way as Object.notify() does. In the same way that you'd check the current state after waking up from a call to Object.wait() (you don't assume that the wakeup means your wait condition has been satisfied), after being nudged with an interrupt you should check why you were interrupted. There is usually a way to do this. For example, java.util.concurrent.FutureTask has an isCancelled() method.
Code sample:
public void run() {
....
try {
.... // Calls that may block.
} catch (InterruptedException e) {
if (!running) { // Add preferred synchronization here.
return; // Explicit flag says we should stop running.
}
// We were interrupted, but the flag says we're still running.
// It would be wrong to always exit here. The interrupt 'nudge'
// could mean something completely different. For example, it
// could be that the thread was blocking on a read from a particular
// file, and now we should read from a different file.
// Interrupt != quit (not necessarily).
}
....
}
public void stop() {
running = false; // Add preferred synchronization here.
myThread.interrupt();
}
The problem with the question is "I". "I" usually refers to a single instance of a class. I mean by that, that any particular piece of low-level code (class) should not rely upon the implementation of the entire system. Having said that you do have make some "architectural" decisions (like what platform to run on).
Possible unexpected interrupts coming from the JRE are canceled tasks in java.util.concurrent and shutting down applets.
Handling of thread interrupts is usually written incorrectly. Therefore, I suggest the architectural decision to avoid causing interrupts where possible. However, code handling interrupts should always be written correctly. Can't take interrupts out of the platform now.
You could learn this by creating your own thread class (extending java.lang.Thread) and overriding interrupt() method, in which you record the stacktrace into, say, a String field, and then transfer to super.interrupt().
public class MyThread extends Thread {
public volatile String interruptStacktrace; // Temporary field for debugging purpose.
#Override
public void interrupt() {
interruptStacktrace = dumpStack(); // You implement it somehow...
super.interrupt();
}
}
As already mentioned, another library can interrupt your threads. Even if the library doesn't have explicit access to the threads from your code, they can still get the list of threads that are running and interrupt them that way with the following method.
I think I understand why you are a bit confused about interruption. Please consider my answers in line:
If I'm never ever interrupting other threads myself, what can trigger an InterruptedException?
Firstly you may interrupt other threads; I know that in JCiP it is mentioned that you should never interrupt threads you do not own; however, this statement has to be properly understood. What it means is that your code which might be running in any arbitrary thread should not handle interruption because since it is not the owner of the thread it has no clue of its interruption policy. So you may request interruption on other threads, but let its owner take the course of interruption action; it has the interruption policy encapsulated within it, not your task code; at least be courteous to set the interruption flag!
There are many ways why there could be interruptions still, may be timeouts, JVM interrupts etc.
If I'm never ever interrupting other threads myself using interrupt() (say because I'm using other means to cancel my working threads, like poison pills and while (!cancelled) style loop [as both explained in JCIP]), what does an InterruptedException then mean? What am I supposed to do upon catching one? Shutdown my app?
You need to be very careful here; if you own the thread which threw InterruptedException (IE), then you know what to do upon catching it, say you may shutdown your app/service or you may replace this killed thread with a new one! However, if you do not own the thread then upon catching IE either rethrow it higher up the call stack or after doing something (may be logging), reset the interrupted status so that the code which owns this thread, when control reaches it, may learn that the thread was interrupted and hence take actions as it will since only it knows the interruption policy.
Hope this helped.
The InterruptedException says that a routine may be interrupted, but not necessarily that it will be.
If you don't expect the interrupt then you should treat it as you might any other unexpected exception. If it's in a critical section where an unexpected exception could have heinous consequences, it might be best to try and clean up resources and gracefully shutdown (because getting the interrupt signals that your well-engineered application that doesn't rely on interrupts is being used in a way it wasn't designed, and so there must be something wrong). Alternatively, if the code in question is something non-critical or trivial, you might want to ignore (or log) the interrupt and keep going.

Categories