Yrl*_*lec 8 java windows multithreading nio crash-dumps
我开发的一个程序偶尔会因为这个错误而崩溃JVM:http://bugs.java.com/bugdatabase/view_bug.do?video_id = 8029516.遗憾的是,Oracle尚未解决该漏洞,并且错误报告称没有已知的解决方法.
我试图通过在KeyWatcher线程中调用.register(sWatchService,eventKinds)来修改bug报告中的示例代码,方法是将所有挂起的注册请求添加到我在KeyWatcher线程中循环但仍在崩溃的列表中.我猜这与sWatchService上的同步效果相同(就像尝试过的bug报告的提交者一样).
你能想出办法解决这个问题吗?
我已经设法创建了一个解决方法,尽管它有点难看。
该错误存在于 JDK 方法中WindowsWatchKey.invalidate(),该方法释放本机缓冲区,而后续调用仍可能访问它。这一单行代码通过将缓冲区清理延迟到 GC 来解决这一问题。
这是JDK 的已编译补丁。为了应用它,添加以下 Java 命令行标志:
-Xbootclasspath/p:jdk-8029516-patch.jar
如果在您的情况下无法选择修补 JDK,那么在应用程序级别上仍然有解决方法。它依赖于 Windows WatchService 内部实现的知识。
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
注册密钥后立即调用JDK_8029516.patch(watchKey),可以防止watchKey.cancel()过早释放本机缓冲区。
| 归档时间: |
|
| 查看次数: |
561 次 |
| 最近记录: |