2016-03-17 41 views
2

問題:
使用WAR文件(在WEB-INF/classes中)部署XCC庫將禁止重新部署/更新該webapp而不重新啓動整個Tomcat容器。它只是停止工作,因爲仍然有資源分配,因此Tomcat無法刪除一些JAR文件。
當部署在雄貓lib目錄庫(如JDBC驅動程序會),在Tomcat Tomcat的日誌中,隨後寫入內存泄漏的警告:如何在Apache Tomcat中部署Marklogic XCC庫?

17-Mar-2016 10:58:45.683 WARNING [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [api] appears to have started a thread named [Thread-4] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Thread.sleep(Native Method) com.marklogic.xcc.ContentSourceFactory$ConnectionCollector.run(ContentSourceFactory.java:449) 

我發現了什麼:
我做了一些調查並發現(至少在XCC 8.0.3中)在ContentSourceFactory中有一個始終不會關閉的線程。該線程正在影響servlet的更新/重新部署並造成內存泄漏。我的快速解決方案是創建一個自定義的ContentSourceFactory,它具有一個在servlet停止時會被調用的關閉方法。

問題:
不幸的是我沒有在文檔中找到任何線索。那麼在servlet容器中使用XCC庫(8.x)的官方方式是什麼?

回答

2

此線程似乎在JVM期間運行。我會爲此打開一個缺陷。

基於tomcat中不同產品的類似問題的經驗的解決方法。數據庫驅動器(特別是JDBC)歷來在這方面存在問題。

將xcc.jar放入tomcat的「共享庫」類路徑中,而不是在WAR中。這通常不被推薦 - 但OTOH正是爲什麼存在共享庫類路徑 - 這允許您的應用程序被重新部署。 XCC代碼是線程安全的並且與上下文無關,只要你不自己共享活動連接對象,它應該可以正常工作。

另外,還要確保你的努力關閉或關閉所有響應對象,終結可能需要很長的時間來踢

-David

0

我的臨時解決方案:
作爲DALDEI提到的,看起來像XCC庫中的一個公開問題。爲了做一個臨時的解決方法,我根據原始來源(8.0.4)寫了一個DisposableContentSourceFactory。代碼可以在這裏找到:https://gist.github.com/Mario-Eis/a16437c35d2aa097f668

該方法還有一個優點,因爲它可以平滑地集成在IoC環境中,例如, Spring IoC。

@Configuration 
public class XccContext { 

    @Bean(destroyMethod = "shutdown") 
    public DisposableContentSourceFactory contentSourceFactory() { 
     return DisposableContentSourceFactory.create(); 
    } 

    @Bean 
    public ContentSource contentSource(XccConfiguration xccConfiguration, DisposableContentSourceFactory contentSourceFactory) throws XccConfigException { 
     return contentSourceFactory.newContentSource(xccConfiguration.connectionString()); 
    } 

    @Bean(destroyMethod = "close") 
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES) 
    public Session marklogicSession(ContentSource contentSource) { 
     return contentSource.newSession(); 
    } 
} 

爲了確保有點「兼容性」官方靜態類的方法,我也包含靜態工廠方法create()

如果有公共GIT存儲庫,我可以提交一個請求。