2015-10-01 212 views
0

我有一個WatchService用於監視新文件夾和修改文件的文件夾。WatchService導致tomcat內存泄漏?

問題:應用一個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 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; 
    } 
} 

回答

2

看起來好像你沒有在你的代碼中調用java.nio.file.WatchService.close()的任何地方; java.nio.file.WatchService工具java.io.Closeable這意味着您可以輕鬆地確保您擺脫相關的java.nio.file.WatchService使用不當造成內存泄漏通過使用try-與資源(因爲Java 7的可用)塊,像這樣:

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. 
+0

我按照建議試過,但仍然有相同的錯誤。在關閉tomcat時,異常將從'watchService.take()'行中記錄。不知何故這條線導致內存泄漏。但爲什麼?也許我可以爲tomcat服務器註冊一個關閉鉤子,並關閉觀察者顯式? – membersound

+0

您是否嘗試過使用'java.nio.file.WatchService#poll(long,java.util.concurrent.TimeUnit)'而不是'watchService.take()'? – Filip

+0

您是否正在使用java.util.concurrent.ExecutorService來運行迄今共享的代碼? – Filip