WatchService导致tomcat内存泄漏?

时间:2015-10-01 07:08:30

标签: java tomcat watchservice

我有一个WatchService用于监控新文件和修改过的文件的文件夹。

问题:应用程序在tomcat服务器上运行,当我关闭服务器时,会记录以下错误消息(加上服务器关闭需要很长时间):

01-Oct-2015 08:58:11.998 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [myapp] appears to have started a thread named [Thread-5] but has failed to stop it. This is very likely to create a memory leak.
Stack trace of thread:
sun.nio.fs.WindowsNativeDispatcher.GetQueuedCompletionStatus0(Native Method)
sun.nio.fs.WindowsNativeDispatcher.GetQueuedCompletionStatus(Unknown Source)
sun.nio.fs.WindowsWatchService$Poller.run(Unknown Source)
java.lang.Thread.run(Unknown Source)

01-Oct-2015 08:58:11.998 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [myapp] appears to have started a thread named [SimpleAsyncTaskExecutor-2] but has failed to stop it. This is very likely to create a memory leak.
Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(Unknown Source)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
java.util.concurrent.LinkedBlockingDeque.takeFirst(Unknown Source)
java.util.concurrent.LinkedBlockingDeque.take(Unknown Source)
sun.nio.fs.AbstractWatchService.take(Unknown Source)

我该如何解决这个问题?我的表服务和往常一样:

WatchService watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get(folder);
path.register(watchService, events);

WatchKey key = null;
while (true) {
    try {
        key = watchService.take();
        for (WatchEvent<?> event : key.pollEvents()) {
            //etc
        }

        key.reset();
    } catch (ClosedWatchServiceException e) {
        break;
    }
}

1 个答案:

答案 0 :(得分:2)

看起来好像你没有在代码中的任何地方调用java.nio.file.WatchService.close(); java.nio.file.WatchService实现java.io.Closeable,这意味着您可以通过使用try-with-resources(自Java 7以来可用)轻松确保消除与java.nio.file.WatchService的不当使用相关的任何内存泄漏块如此:

try(WatchService watchService = FileSystems.getDefault().newWatchService()) {

    Path path = Paths.get(folder);
    path.register(watchService, events);

    WatchKey key = null;
    while (true) {
        try {
            key = watchService.take();
            for (WatchEvent<?> event : key.pollEvents()) {
                //etc
            }

            key.reset();

        } catch(InterruptedException | ClosedWatchServiceException e) { 
            Thread.currentThread().interrupt();            
        }
    }
}

另外请查看WatchService java spec,阅读文档通常会有很多帮助。

The close method may be invoked at any time to close the service causing any threads waiting to retrieve keys, to throw ClosedWatchServiceException.