直接停止Tomcat8後提示的警告異常如下圖所示,共有四個警告 :
-
從圖中可以看出,共有四個警告異常: 第一個:數據庫鏈接未釋放,被強制反註冊 第二個~第四個:應用關閉,但是線程未釋放,導致報出了可能會有內存溢出的警告
解決方法:
第一個:參考了網上諸多大神的博客,添加如下監聽器,可解決第一個數據庫鏈接未釋放問題,此解決方法在我的項目中可以起到作用;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
@Configuration
public class UnregisterDataSourceListener implements ServletContextListener {
Logger logger = LoggerFactory.getLogger(UnregisterDataSourceListener.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
// On Application Startup, please…
// Usually I'll make a singleton in here, set up my pool, etc.
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
logger.debug("deregistering jdbc driver:{}", driver);
} catch (SQLException e) {
e.printStackTrace();
logger.debug("Error deregistering driver:{}", driver);
logger.debug("Error message:{}", e.getMessage());
}
}
}
}
第二個~第四個:
主要是由於我的項目中在啓動時需要加載企業微信的配置,獲取Token,故啓動了一個線程獲取,最後線程未被回收,修改了一個監聽器,改爲實現ServletContextListener後又減少了一個警告:
import com.supplychain.controller.wechat.TokenThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* token失效管理
* @author Hangele
* @since 2018-09-17
*/
@Configuration
public class InitAppIdAndSecret implements ServletContextListener {
private static Logger logger = LoggerFactory.getLogger(InitAppIdAndSecret.class);
public void contextInitialized(ServletContextEvent e) {
logger.info("contextInitialized starting");
// 啓動定時獲取access_token的線程,暫時先拿掉,調試微信時再開放。
String os = System.getProperty("os.name");
logger.info(" 當前操作系統環境爲:{}", os);
if (os.toLowerCase().startsWith("win")) {
logger.info("windows環境,access_token的線程不啓動");
} else {
logger.info("啓動定時獲取access_token的線程............");
new Thread(new TokenThread()).start();
}
logger.info("contextInitialized ends");
}
public void contextDestroyed(ServletContextEvent e) {
logger.info("contextDestroyed starting");
System.gc();
logger.info("contextDestroyed ends");
}
}
在釋放上下文時,調用了GC但是好像並沒有起到作用,還是要另尋辦法,先記錄至此!
修改後,效果如下圖所示:
暫時去掉了兩個,線程未釋放目前還未解決,不知道GC啥時候會回收…