1. 程式人生 > >This is very likely to create a memory leak. Stack trace of thread錯誤分析

This is very likely to create a memory leak. Stack trace of thread錯誤分析

1、問題描述

啟動tomcat部署專案時,報This is very likely to create a memory leak. Stack trace of thread錯誤。

29-May-2018 12:30:09.322 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal One or more Filters failed to start. Full details will be found in the appropriate container log file
29
-May-2018 12:30:09.323 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal Context [] startup failed due to previous errors 29-May-2018 12:30:09.427 WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [ROOT] registered the JDBC driver [com.alibaba.druid.proxy.DruidDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered. 29
-May-2018 12:30:09.427 WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [ROOT] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered. 29
-May-2018 12:30:09.428 WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [ROOT] registered the JDBC driver [org.h2.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered. 29-May-2018 12:30:09.428 WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:64) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) java.lang.Thread.run(Thread.java:745)

2、問題原因

tomcat啟動奔潰,同時釋放了jdbc連線。

3、解決方案

這種異常造成的原因千奇百怪,並沒有統一的處理方案,以下是我遇到的不同情況採取的幾種解決方案。

3.1、存在多個tomcat子執行緒

啟動前tomcat意外退出,使用ps -ef | grep "tomcat名稱"檢視是不是有多個tomcat在啟動,若有,Kill掉。

3.2、調整JVM引數

JAVA_OPTS='-server -Xms5120m -Xmx10240m -XX:PermSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=5120m '

3.3、去掉tomcat監聽

tomcat 6.025以後引入了記憶體洩露偵測,對於垃圾回收不能處理的對像,它就會做日誌。去掉監聽的方法也很簡單:
在tomcat的server.xml檔案中,把
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
這個監聽給關了。

3.4、其他

如果以上方案無法解決問題,只能逐步排查,排查方案如下:
1.使用“之前部署正常的分支”(我們記為hoaven分支)部署專案;
2.若tomcat能正常啟動,說明tomcat或伺服器沒有問題,檢查自己的程式碼;
3.逐步檢查自己的程式碼:從hoaven分支checkout一個分支(fixbug),然後將自己寫的程式碼一點一點移至fixbug分支。
4.每移動一次程式碼,部署一次,若正常啟動,繼續移動程式碼;若報出以上錯誤,停止移動,檢查本次移動的程式碼。

其實3.4方法很有效,特別是檢查肉眼無法明瞭的莫名其妙的的bug。
記錄下我某一次檢查以上bug採用的3.4方案,得出的結果:
程式碼中,有一處注入報錯很奇怪:

@Slf4j
@Component
public class RestAuthFilter extends FormAuthenticationFilter {

    @Resource
    MobileDeviceService mobileDeviceService;

    @Resource
    UserService userService;

    ...
}


@Slf4j
@Service
public class MobileDeviceServiceImpl implements MobileDeviceService {
    @Resource
    IHddBaseService hddBaseService;

    ...
}

MobileDeviceServiceUserService上的@Resource改為@Autowired部署則沒有問題,思考一下:@Resource屬於jdk的註解,@Autowired屬於spring的註解,應該是注入RestAuthFilter時,在spring容器中沒有找到MobileDeviceService和UserService的例項,@Resource會強制將MobileDeviceServiceUserService注入進來,而@Autowired採取的措施是不注入(或注入null)。這樣一來,就會有新的問題,MobileDeviceServiceUserService例項為null,解決方案在後面的部落格解決。