最多見的緣由爲:html
有多是內存分配確實太小,而正常業務使用了大量內存java
某一個對象被頻繁申請,卻沒有釋放,內存不斷泄漏,致使內存耗盡python
某一個資源被頻繁申請,系統資源耗盡,例如:不斷建立線程,不斷髮起網絡鏈接ios
經過jprofer觀察全部對象,觸發gc後觀察變化。獲得不斷遞增的對象找到問題點。web
經過命令排查算法
確認是否是內存自己就分配太小數據庫
方法:jmap -heap pid編程
能夠查看新生代,老生代堆內存的分配大小以及使用狀況,看是否自己分配太小。tomcat
找到最耗內存的對象安全
方法:jmap -histo:live pid | more
輸入命令後,會以表格的形式顯示存活對象的信息,並按照所佔內存大小排序
確認是不是資源耗盡
工具:
pstree
netstat
查看進程建立的線程數,以及網絡鏈接數,若是資源耗盡,也可能出現OOM。
這裏介紹另外一種方法,經過
/proc/${PID}/fd
/proc/${PID}/task
能夠分別查看句柄詳情和線程數。
例如,某一臺線上服務器的sshd進程PID是9339,查看
ll /proc/9339/fd
ll /proc/9339/task
https://mp.weixin.qq.com/s/tVvqVVigmvzLfPjnt2oK0g
經過對dump文件分析,jvisualvm查看對象,分析佔內存最多的對象,查看對象內容,找到對象引用找到問題點。
http://blog.csdn.net/wilsonpeng3/article/details/70064336
棧溢出徹底解讀 (StackOverflowError)
致使棧溢出的緣由不少,提三個主要的:
https://mp.weixin.qq.com/s/1d8W-eyzsnGDr9-uSfag6Q
根據top命令,發現cpu佔用高的進程PID,或者經過ps aux | grep PID命令查看。
定位到具體線程: ps -mp pid -o THREAD,tid,time 或者 ps -Lfp pid 或者 top -Hp pid,看到具體線程佔用cpu比例和時間
將tid轉成16進制數字:printf "%x\n" tid
最後打印出線程棧信息:jstack pid |grep tid -A 30
https://mp.weixin.qq.com/s/fU4i-jDVHgdJfRtWtXaxrQ
https://mp.weixin.qq.com/s/c-KuGjI_VH1dTxIWtxZJEg
https://www.cnblogs.com/ylz8401/p/6170775.html
http://blog.csdn.net/zhouree/article/details/45153417
http://blog.csdn.net/zhanglh046/article/details/50443528
http://www.xitongzhijia.net/xtjc/20141203/31828.html
java查看線程死鎖 JConsole,選擇監控進程後,選擇 查看死鎖線程,能夠列出死鎖/阻塞線程
https://my.oschina.net/u/3705388/blog/1596538
本質是 jstack 獲取線程棧,
找出Thread.State:BLOCKED的線程,對比線程waiting to lock<xxx> 和locked<yyy>,
有沒有兩個線程的xxx和yyy是相反的,即相互等待對方持有的鎖。
IO高如何定位
Step1 : iostat 查看IO狀況
Step2: iotop定位負載來源進程
iotop的本質是一個python腳本,從proc中獲取thread的IO信息,進行彙總。
Step3 pt-ioprofile定位負載來源文件
pt-ioprofile的原理是對某個pid附加一個strace進程進行IO分析。
https://www.cnblogs.com/zengkefu/p/5634306.html
https://blog.csdn.net/aquester/article/details/51557879
線上動態增長接口調用狀況方法:
BTrace是Java的安全可靠的動態跟蹤工具。 他的工做原理是經過 instrument + asm 來對正在運行的java程序中的class類進行動態加強,能夠在不用重啓的狀況下監控系統運行狀況,方便的獲取程序運行時的數據信息,如方法參數、返回值、全局變量和堆棧信息等,而且作到最少的侵入,佔用最少的系統資源。
https://my.oschina.net/u/3705388/blog/1615376
G1收集器
並行與併發(充分利用多核多CPU縮短STW時間) 分代收集(獨立管理整個Java堆,但針對不一樣年齡的對象採起不一樣的策略) 空間整合(局部看是基於複製算法,從總體來看是基於標記-整理算法,都不會產生內存碎片) 可預測的停頓(能夠明確指定在一個長度爲M毫秒的時間片內垃圾收集不會超過N毫秒)
初始標記(標記一下GC Roots能直接關聯的對象並修改TAMS值,須要STW但耗時很短) 併發標記(從GC Root從堆中對象進行可達性分析找存活的對象,耗時較長但能夠與用戶線程併發執行) 最終標記(爲了修正併發標記期間產生變更的那一部分標記記錄,這一期間的變化記錄在Remembered Set Log裏,而後合併到Remembered Set裏,該階段須要STW可是可並行執行) 篩選回收(對各個Region回收價值排序,根據用戶指望的GC停頓時間制定回收計劃來回收);
g1 和 cms 區別,吞吐量優先和響應優先的垃圾收集器選擇
CMS是一種以最短停頓時間爲目標的收集器
響應優先選擇CMS,吞吐量高選擇G1
http://blog.csdn.net/lk7688535/article/details/51767460
http://blog.csdn.net/u012969412/article/details/76614988
jvm工具命令排查線上問題
http://blog.csdn.net/u010827436/article/details/46564641
-server --啓用可以執行優化的編譯器,顯著提升服務器的性能 -Xmx4000M --堆最大值 -Xms4000M --堆初始大小 -Xmn600M --年輕代大小 -XX:PermSize=200M --持久代初始大小 -XX:MaxPermSize=200M --持久代最大值 -Xss256K --每一個線程的棧大小 -XX:+DisableExplicitGC --關閉System.gc() -XX:SurvivorRatio=1 --年輕代中Eden區與兩個Survivor區的比值 -XX:+UseConcMarkSweepGC --使用CMS內存收集 -XX:+UseParNewGC --設置年輕代爲並行收集 -XX:+CMSParallelRemarkEnabled --下降標記停頓 -XX:+UseCMSCompactAtFullCollection --在FULL GC的時候,對年老代進行壓縮,可能會影響性能,可是能夠消除碎片 -XX:CMSFullGCsBeforeCompaction=0 --此值設置運行多少次GC之後對內存空間進行壓縮、整理 -XX:+CMSClassUnloadingEnabled --回收動態生成的代理類 SEE:http://stackoverflow.com/questions/3334911/what-does-jvm-flag-cmsclassunloadingenabled-actually-do -XX:LargePageSizeInBytes=128M --內存頁的大小不可設置過大, 會影響Perm的大小 -XX:+UseFastAccessorMethods --原始類型的快速優化 -XX:+UseCMSInitiatingOccupancyOnly --使用手動定義初始化定義開始CMS收集,禁止hostspot自行觸發CMS GC -XX:CMSInitiatingOccupancyFraction=80 --使用cms做爲垃圾回收,使用80%後開始CMS收集 -XX:SoftRefLRUPolicyMSPerMB=0 --每兆堆空閒空間中SoftReference的存活時間 -XX:+PrintGCDetails --輸出GC日誌詳情信息 -XX:+PrintGCApplicationStoppedTime --輸出垃圾回收期間程序暫停的時間 -Xloggc:$WEB_APP_HOME/.tomcat/logs/gc.log --把相關日誌信息記錄到文件以便分析. -XX:+HeapDumpOnOutOfMemoryError --發生內存溢出時生成heapdump文件 -XX:HeapDumpPath=$WEB_APP_HOME/.tomcat/logs/heapdump.hprof --heapdump文件地址
******* http://ginobefunny.com/post/jvm_interview_questions/
OOM定位排查 (用jmap看內存狀況,而後用 jstack主要用來查看某個Java進程內的線程堆棧信息)
A.java.lang.OutOfMemoryError: Java heap space
最多見的緣由:
1.應用程序須要的堆空間比JVM提供的大。 經過-Xmx5G 配置增長堆空間大小
2.流量/數據量峯值:應用程序在設計之初均有用戶量和數據量的限制,某一時刻,當用戶數量或數據量忽然達到一個峯值,而且這個峯值已經超過了設計之初預期的閾值,那麼之前正常的功能將會中止,並觸發java.lang.OutOfMemoryError: Java heap space
異常。
3.內存泄漏:特定的編程錯誤會致使你的應用程序不停的消耗更多的內存,每次使用有內存泄漏風險的功能就會留下一些不能被回收的對象到堆空間中,隨着時間的推移,泄漏的對象會消耗全部的堆空間,最終觸發java.lang.OutOfMemoryError: Java heap space
錯誤。
2.3經過Debuggers, profilers, heap dump analyzers
等工具,可讓你的程序最大程度的避免內存泄漏問題。
B.java.lang.OutOfMemoryError:GC overhead limit exceeded
當應用程序花費超過98%的時間用來作GC而且回收了不到2%的堆內存時,會拋出java.lang.OutOfMemoryError:GC overhead limit exceeded
錯誤。具體的表現就是你的應用幾乎耗盡全部可用內存,而且GC屢次均未能清理乾淨。解決辦法同上面2.3
C.java.lang.OutOfMemoryError: PermGen space
錯誤就代表持久代所在區域的內存已被耗盡。
緣由是:太多的類或者太大的類被加載到permanent generation
(持久代)。
持久代主要存儲的是每一個類的信息,好比:類加載器引用、運行時常量池(全部常量、字段引用、方法引用、屬性)、字段(Field)數據、方法(Method)數據、方法代碼、方法字節碼等等。咱們能夠推斷出,PermGen
的大小取決於被加載類的數量以及類的大小。
-XX:MaxPermSize參數 設置持久帶大小
分析dump文件:首先,找出引用在哪裏被持有;其次,給你的web應用程序添加一個關閉的hook,或者在應用程序卸載後移除引用。你可使用以下命令導出dump文件:
jmap -dump:format=b,file=dump.hprof <process-id>
當你拿到生成的堆轉儲文件,並利用像Eclipse Memory Analyzer Toolkit這樣的工具來尋找應該卸載卻沒被卸載的類加載器,而後對該類加載器加載的類進行排查,找到可疑對象,分析使用或者生成這些類的代碼,查找產生問題的根源並解決它。
https://www.jianshu.com/p/2fdee831ed03
https://www.cnblogs.com/itar/p/7424311.html
https://www.cnblogs.com/wbyp/p/7753528.html
http://blog.csdn.net/garfielder007/article/details/55822985