我开发的一个程序偶尔会由于这个错误而导致 JVM 崩溃:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8029516 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8029516。不幸的是,Oracle 尚未解决该错误,并且错误报告称没有已知的解决方法。
我尝试通过在 KeyWatcher 线程中调用 .register(sWatchService, eventKinds) 来修改错误报告中的示例代码,将所有挂起的注册请求添加到我在 KeyWatcher 线程中循环的列表中,但它仍然崩溃。我猜这与在 sWatchService 上同步具有相同的效果(就像错误报告的提交者尝试的那样)。
你能想出什么办法来解决这个问题吗?
来自评论:
当有待处理的 ReadDirectoryChangesW 未完成时,我们似乎遇到了 I/O 取消问题。
声明和示例代码表明该错误在以下情况下触发:
- 有一个尚未消耗的待处理事件(它可能对用户可见,也可能不可见)
WatchService.poll()
or WatchService.take()
)
-
WatchKey.cancel()
被调用的键
这是一个令人讨厌的错误,没有通用的解决方法。该方法取决于您的应用程序的具体情况。考虑将手表集中到一个地方,这样您就不需要打电话WatchKey.cancel()
。如果在某一时刻池变得太大,请关闭整个池WatchService
并重新开始。类似的东西。
public class FileWatcerService {
static Kind<?>[] allEvents = new Kind<?>[] {
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY
};
WatchService ws;
// Keep track of paths and registered listeners
Map<String, List<FileChangeListener>> listeners = new ConcurrentHashMap<String, List<FileChangeListener>>();
Map<WatchKey, String> keys = new ConcurrentHashMap<WatchKey, String>();
boolean toStop = false;
public interface FileChangeListener {
void onChange();
}
public void addFileChangeListener(String path, FileChangeListener l) {
if(!listeners.containsKey(path)) {
listeners.put(path, new ArrayList<FileChangeListener>());
keys.put(Paths.get(path).register(ws, allEvents), path);
}
listeners.get(path).add(l);
}
public void removeFileChangeListener(String path, FileChangeListener l) {
if(listeners.containsKey(path))
listeners.get(path).remove(l);
}
public void start() {
ws = FileSystems.getDefault().newWatchService();
new Thread(new Runnable() {
public void run() {
while(!toStop) {
WatchKey key = ws.take();
for(FileChangeListener l: listeners.get(keys.get(key)))
l.onChange();
}
}
}).start();
}
public void stop() {
toStop = true;
ws.close();
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)