首先,以後碰到任何jvm的錯誤,先看日志!!!!!!!!
web項目在tomcat目錄下的log裡,或者自己設定的errorfile目錄下。總之,找到一切可以運用的日志,比如crash日志,coredump日志等,可以快速确定問題所在。
不過這次調查奇怪的很,不管是jvm還是tomcat,都沒有任何錯誤日志報出。真讓人難受。
經過學習,得知有一個linux指令可以助我一臂之力(感謝此指令) 那就是萬能的sudo dmesg -T | grep "java"。果然,指令一出,效果空前,發現一條類似這樣的錯誤。
localhost kernel: java: segfault at ip sp error 7 in libjvm.so
作為一個優秀的垃圾,我表示不懂這是啥(後來才知道,這就足夠了啊。。。。),這條資訊大概的意思如下。libjvm.so(共享動态庫)運作時出現段錯誤。我就在想,這個error 7是什麼意思?解讀如下:
段錯誤中(segfault error),7是要解讀為二進制的,即111 這個111每位對應如下:
1: 表示是使用者态程式記憶體通路越界,值為0表示是核心态程式記憶體通路越界。
1: 表示是寫操作導緻記憶體通路越界,值為0表示是讀操作導緻記憶體通路越界。
0: 表示通路的非法位址根本沒有對應的頁面,也就是無效位址,值為1表示沒有足夠的權限通路非法位址的内容。
是以我的問題就是:使用者态程式記憶體通路越界,寫操作導緻記憶體通路越界,沒有足夠的權限通路非法位址的内容。
好,問題放這裡,開始我的吐槽。
從别人手中接手一個項目,起初說是不穩定,隻要一運作某個程式,tomcat會直接死掉。然後這個人交給我後就跑路了,天真的我以為是個小活,因為以前隻是有過一些jvm的基礎知識,雖然這是第一次碰到真實情景,但是我垃圾人膽大(上司都說交給我了,我能不做?)是以我就欣(bei)然(po)接受了。
首先我閱讀代碼,了解業務邏輯。邊了解代碼邊改動代碼(邊改邊罵,這是魔鬼寫的代碼嗎,錯誤太多,用法奇葩,即便不是後來發現的主要原因,程式原有的錯誤也真讓人腦袋大)。
一天半以後,了解的差不多了,改的也差不多了,就開始我的頭大之路。首先我懷疑是記憶體洩漏(是以說,一定要找到所有可用日志再去解決問題,唉,沒經驗),渣渣的我隻想到了jconsole工具,好巧不巧的是,測試了兩次,程式當掉的時候還都是survivor區炸掉。是以我就開始了調優。
同時jvm是被linux主動殺死的,接受了11信号,網上很多說有時候是因為程式記憶體占用過大導緻系統自我保護而殺死程序,是以我深信不疑是記憶體問題了(當然了,搞了半天都白搞了)。如果有需要的可以看看,程式運作時的參數如下:-Xms128m -Xmx128m。然後還不行,還是會死,那我想啊,我的機器到底還剩了多少記憶體了?執行free -h 嘿嘿嘿 隻剩下79M了。。。。
是以啊,我打算繼續調優eclipse,畢竟開了eclipse之後,記憶體從1.2G銳減到79M。在eclipse的安裝目錄裡,有個eclipse.ini配置檔案,加入參數如下:
-Xms128m
-Xmx128m
-XX:PermSize=128m
-XX:MaxPermSize=128m
-XX:+UseParallelGC
進入eclipse後,進入window->preferences->general->startupandshutdown->取消所有啟動項(如果隻是簡單的開發java及javaee)。
配置完之後發現,有點用,有效記憶體剩了300M了,同時啟動好像也快了一點哦。(這并非最優配置,且不說每個機器配置不一樣,我這個128m配置設定就很随意,等好好了解了我再更新)。
還是沒有解決問題,嘿嘿嘿。怎麼辦呢,一行一行測試!是的,就是注釋入口的所有代碼,從第一行開始一行一行解注釋,并且每次解注釋運作2000次。辦法雖笨,還真管用,最後定位到一個so動态庫。
讓c的小夥伴好好查錯并重新生成,問題解決。。。。。。。
再貢獻一點點
實在沒有任何日志,可以進行如下辦法:
(1)開啟linux 的core檔案生成,Core檔案其實就是記憶體的映像,當程式崩潰時,存儲記憶體的相應資訊,主用用于對程式進行調試。
當程式崩潰時便會産生core檔案,其實準确的應該說是core dump 檔案,預設生成位置與可執行程式位于同一目錄下,檔案名為core.***,其中***是某一數字。
ulimit -c 0 關閉core生成
開啟步驟:sudo vim /etc/profile 在末尾添加 ulimit -S -c unlimited >/dev/null 2>&1
(2)當程式意外被kill後,在程式目錄或者根目錄 會生成生成core.***檔案。用 gdb java core.***進行調試。