繁体   English   中英

如何编写响应`Thread.interrupt()`的本机代码?

[英]How do I write native code which responds to `Thread.interrupt()`?

在Java中,所有标准的阻塞方法都可以通过调用Thread.interrupt()来中断,但是如果我们有Java绑定包装一个本地库来执行它自己的I / O呢? 那么本机代码应该如何挂钩到Thread并响应对Thread.interrupt()调用呢?

示例代码

有关完整写入(包括可运行的示例代码),请参阅https://github.com/NWilson/javaInterruptHook

Thread.interrupt()如何工作?

在Sun的JRE(和OpenJDK)中, interrupt()能够唤醒一些低级操作本身,例如在监视器上等待( Object.wait() ),并为更高级别的代码提供内部钩子。通知中断。 这是通过JavaLangAccess.blockedOn()提供的,如果您愿意使用特定于Sun的实现细节,则可以通过sun.misc.SharedSecrets直接通过代码直接调用它。

据我所知,只有一种公开的,记录的方式来注册该通知,即使用java.nio.channels.spi.AbstractSelector 这是Selector的部分实现,它为您提供了将JavaLangAccess.blockedOn()通知连接到选择器的wakeup()方法的脏工作。

如何实现这一切

实现AbstractSelector来创建自己的选择器; 大多数方法都不相关,所以只需忽略它们并放入存根来关闭编译器。 当您要输入JNI阻塞方法时,请调用AbstractSelector begin()方法,然后在返回JNI调用时调用end()

选择器应在其wakeup()实现中取消JNI方法。

粗糙的代码

(有关完整运行的示例,请参阅顶部链接的github repo。)

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();
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM