1. 程式人生 > >記一次由jdk版本導致的錯誤

記一次由jdk版本導致的錯誤

異常表現

專案本地開發環境啟動正常, 部署到生產環境啟動卡死.

解決步驟

  1. 首先當然是找到啟動日誌. 由於專案在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. … …

  1. 到網上查詢解決辦法, 都說是Mybatis的Mapper檔案解析出錯導致, 但是反覆檢查Mapper檔案, 並與上一版本專案部署時的程式碼進行核對, 並沒有發現錯誤.
  2. 經過遠端除錯, 最終找到異常, 是由於新增的一個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中找到了問題: 迴圈輸出的日誌

遠端斷點除錯

  1. 配置伺服器的tomcat開啟遠端斷點除錯監聽:

SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8081,server=y,suspend=n

  1. Eclipse連線遠端伺服器: 除錯配置
  2. 根據網上查詢到的斷點位置, 在圖上位置加上斷點: 在這裡插入圖片描述

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) 方法

  1. 使用startup.bat啟動遠端服務.
  2. 啟動Eclipse遠端除錯.
  3. 結果上面第一個斷點處一直進入, 第二個斷點沒有反應. 我把第一個斷點關掉. 過了一會, 進入第二個斷點. 在這裡插入圖片描述 終於得到錯誤日誌了: 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, 所以出錯.

問題總結

引起這個問題有兩方面原因:

  1. 開發環境管理混亂, 沒有使用統一的jdk版本進行控制.
  2. 專案的日誌管理存在問題. 下圖中實際上是應該輸出錯誤日誌的, 這樣就會更好的解決問題. 在這裡插入圖片描述 最後發現log4j與logback衝突導致日誌輸出出現問題, 錯誤日誌沒有輸出出來: 在這裡插入圖片描述