导致崩溃转储的Java错误的解决方法 [英] Workaround for Java bug which causes crash dump

查看:228
本文介绍了导致崩溃转储的Java错误的解决方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于这个错误,我开发的程序偶尔会崩溃JVM: http:// bugs.java.com/bugdatabase/view_bug.do?bug_id=8029516 。不幸的是,Oracle尚未解决该漏洞,并且错误报告称没有已知的解决方法。

A program that I've developed is crashing the JVM occasionally due to this bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8029516. Unfortunately the bug has not been resolved by Oracle and the bug report says that there are no known workarounds.

我试图通过在KeyWatcher线程中调用.register(sWatchService,eventKinds)来修改错误报告中的示例代码,方法是将所有挂起的注册请求添加到我在KeyWatcher线程中循环的列表,但它仍然崩溃。我猜这与sWatchService上的同步效果相同(就像尝试过的bug报告的提交者一样)。

I've tried to modify the example code from the bug report by calling .register(sWatchService, eventKinds) in the KeyWatcher thread instead, by adding all pending register request to a list that I loop through in the KeyWatcher thread but it's still crashing. I'm guessing this just had the same effect as synchronizing on sWatchService (like the submitter of the bug report tried).

你能想出办法解决这个问题吗? ?

Can you think of any way to get around this?

推荐答案

我设法创建了一个变通方法虽然有点难看。

I've managed to create a workaround though it's somewhat ugly.

该错误在JDK方法 WindowsWatchKey.invalidate()中释放本机缓冲区,而后续调用仍可访问它。 此单线程通过将缓冲区清理延迟到GC来解决问题。

The bug is in JDK method WindowsWatchKey.invalidate() that releases native buffer while the subsequent calls may still access it. This one-liner fixes the problem by delaying buffer clean-up until GC.

以下是JDK的已编译补丁。要应用它,请添加以下Java命令行标志:

-Xbootclasspath / p:jdk-8029516-patch.jar

Here is a compiled patch to JDK. In order to apply it add the following Java command-line flag:
-Xbootclasspath/p:jdk-8029516-patch.jar

如果在您的情况下修补JDK不是一个选项,那么应用程序级别上仍有一个解决方法。它依赖于Windows WatchService内部实现的知识。

If patching JDK is not an option in your case, there is still a workaround on the application level. It relies on the knowledge of Windows WatchService internal implementation.

public class JDK_8029516 {
    private static final Field bufferField = getField("sun.nio.fs.WindowsWatchService$WindowsWatchKey", "buffer");
    private static final Field cleanerField = getField("sun.nio.fs.NativeBuffer", "cleaner");
    private static final Cleaner dummyCleaner = Cleaner.create(Thread.class, new Thread());

    private static Field getField(String className, String fieldName) {
        try {
            Field f = Class.forName(className).getDeclaredField(fieldName);
            f.setAccessible(true);
            return f;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    public static void patch(WatchKey key) {
        try {
            cleanerField.set(bufferField.get(key), dummyCleaner);
        } catch (IllegalAccessException e) {
            throw new IllegalStateException(e);
        }
    }
}

致电 JDK_8029516.patch(watchKey)在注册密钥之后,它将阻止 watchKey.cancel()过早地释放本机缓冲区。

Call JDK_8029516.patch(watchKey) right after the key is registred, and it will prevent watchKey.cancel() from releasing the native buffer prematurely.

这篇关于导致崩溃转储的Java错误的解决方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆