In Java, all the standard blocking methods can be interrupted by calling Thread.interrupt()
, but what if we have Java bindings wrapping a native library which does its own I/O? How then should the native code hook into the Thread and respond to calls to Thread.interrupt()
?
interrupt() method: If any thread is in sleeping or waiting for a state then using the interrupt() method, we can interrupt the execution of that thread by showing InterruptedException. A thread that is in the sleeping or waiting state can be interrupted with the help of the interrupt() method of Thread class.
The "interrupted" status of the thread is set to true. If the thread is currently blocked by a call to sleep or wait, an InterruptedException is thrown. tests whether or not the current thread (that is, the thread that is executing this instruction) has been interrupted. Note that this is a static method.
An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.
currentThread(). interrupt() in Interruptible Methods? By an interruptible method, we mean a blocking method that may throw InterruptedException , for example, Thread. sleep() , BlockingQueue.
For a full writeup, including runnable sample code, see https://github.com/NWilson/javaInterruptHook.
Thread.interrupt()
work?In Sun's JRE (and OpenJDK), interrupt()
is able to wake up a few low-level operations itself, such as waiting on a monitor (Object.wait()
), and provides an internal hook for higher-level code to be notified of the interruption. This is provided through JavaLangAccess.blockedOn()
, which can actually be called directly by your code through sun.misc.SharedSecrets
, if you're willing to use Sun-specific implementation details.
As far as I can tell, there's only one public, documented way to register for that notification, which is using java.nio.channels.spi.AbstractSelector
. This is a partial implementation of Selector
which does the dirty work for you of hooking up the JavaLangAccess.blockedOn()
notification to the selector's wakeup()
method.
Implement AbstractSelector
to make your own selector; most of the methods are not relevant so just ignore them and put in stubs to shut up the compiler. When you are about to enter your JNI blocking method, call the AbstractSelector
begin()
method, then call end()
when the JNI call has returned.
The selector should cancel the JNI method in its implementation of wakeup()
.
(For a full running example see the github repo linked at the top.)
class NativeTask {
public NativeTask() {}
public void doTask()
throws InterruptedException {
NativeTaskSelector selector = new NativeTaskSelector(this);
try {
selector.registerStart();
doTask0(); // native method
if (Thread.interrupted())
throw new InterruptedException();
} finally {
selector.registerEnd();
try { selector.close(); } catch (IOException impossible) {}
}
}
/* The long-running native operation. */
native private void doTask0();
public void wakeupTask() { wakeupTask0(); }
/* A way to cause the native operation to wake up. */
native private void wakeupTask0();
}
class NativeTaskSelector extends AbstractSelector {
protected NativeTaskSelector(NativeTask task_) {
super(null);
task = task_;
}
public void registerStart() { begin(); }
public void registerEnd() { end(); }
final private NativeTask task;
@Override
public Selector wakeup() {
task.wakeupTask();
return this;
}
@Override
protected void implCloseSelector() throws IOException {
}
@Override
protected SelectionKey register(AbstractSelectableChannel arg0, int arg1,
Object arg2) {
throw new UnsupportedOperationException();
}
@Override
public Set<SelectionKey> keys() {
throw new UnsupportedOperationException();
}
@Override
public int select() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int select(long arg0) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int selectNow() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public Set<SelectionKey> selectedKeys() {
throw new UnsupportedOperationException();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With