記一次由jdk版本導致的錯誤
異常表現
專案本地開發環境啟動正常, 部署到生產環境啟動卡死.
解決步驟
- 首先當然是找到啟動日誌. 由於專案在windows Server 2012上執行, 註冊為windows服務. 所以不會有控制檯日誌, 所有日誌均需要在日誌資料夾中找到. 最終發現無限迴圈輸出日誌:
Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter. Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter. Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter. Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter. … …
- 到網上查詢解決辦法, 都說是Mybatis的Mapper檔案解析出錯導致, 但是反覆檢查Mapper檔案, 並與上一版本專案部署時的程式碼進行核對, 並沒有發現錯誤.
- 經過遠端除錯, 最終找到異常, 是由於新增的一個jar包是通過jdk1.8打包的. 而整個專案的環境一直執行在jdk1.7環境下, 最終導致上面的一系列問題.
詳細解決過程
檢視Tomcat日誌檔案
- catalina.日期.log – 這個主要是記錄tomcat啟動時候的資訊,類似於我們在eclipse中啟動服務的時候在控制檯看到的資訊。在裡面可以看到啟動的JVM引數以及作業系統等日誌資訊。如果沒有使用log4j等日誌機制,系統的的錯誤資訊與列印語句也在這個日誌檔案中記錄。(linux下所有的日誌都在catalina.out中)
- commons-daemon.日期.log – 這個日期放的估計是利用服務方式啟動tomcat作為守護程序的日誌記錄,因為我的tomcat啟動方式是以服務的方式啟動的,索引產生這個日誌檔案記錄了服務的啟動狀態。
- host-manager.日期.log – 這個估計是放tomcat的自帶的manager專案的日誌資訊的,也沒有看到有什麼重要的日誌資訊.
- localhost.日期.log – 這個類似於第一種日誌,可是資訊沒有第一種全
- localhost_access_log.日期.txt – 這個是存放訪問tomcat的請求的所有地址以及請求的路徑、時間,請求協議以及返回碼等資訊(重要)
- manager.日誌.log – 這個估計也是manager專案專有的日誌檔案,看不出有什麼重要的資訊
- tomcat7-stderr.日期.log – 這個是log4j的錯誤日誌,因此在程式中要合理的捕捉異常。
- tomcat7-stdout.日期.log(類似於eclipse的控制檯的資訊) – 這個是程式中的System語句列印的日誌(包括系統丟擲的異常),也終於明白了為什麼一再強調不能用列印語句進行系統除錯
最後在tomcat7-stdout.2018-10-11.log中找到了問題:
遠端斷點除錯
- 配置伺服器的tomcat開啟遠端斷點除錯監聽:
SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8081,server=y,suspend=n
- Eclipse連線遠端伺服器:
- 根據網上查詢到的斷點位置, 在圖上位置加上斷點:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory的protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs)方法 org.springframework.beans.factory.support.AbstractBeanFactory的protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) 方法
- 使用startup.bat啟動遠端服務.
- 啟動Eclipse遠端除錯.
- 結果上面第一個斷點處一直進入, 第二個斷點沒有反應. 我把第一個斷點關掉. 過了一會, 進入第二個斷點. 終於得到錯誤日誌了: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sqlSessionFactory’ defined in class path resource [mapper/applicationContext-db.xml]: Invocation of init method failed; nested exception is java.lang.UnsupportedClassVersionError: com/frog/report/model/DataSource : Unsupported major.minor version 52.0 (unable to load class com.frog.report.model.DataSource) 同時發現每列印一句之前迴圈輸出的日誌, 就進入斷點一次. 根據上面的錯誤日誌, 可以知道version52.0對應的是jdk1.8, 而我們的專案使用的是jdk1.7, 所以出錯.
問題總結
引起這個問題有兩方面原因:
- 開發環境管理混亂, 沒有使用統一的jdk版本進行控制.
- 專案的日誌管理存在問題. 下圖中實際上是應該輸出錯誤日誌的, 這樣就會更好的解決問題. 最後發現log4j與logback衝突導致日誌輸出出現問題, 錯誤日誌沒有輸出出來: