111111111111111111111111JVM面試問題總結

OOM如何解決?

最多見的緣由爲:html

  • 有多是內存分配確實太小,而正常業務使用了大量內存java

  • 某一個對象被頻繁申請,卻沒有釋放,內存不斷泄漏,致使內存耗盡python

  • 某一個資源被頻繁申請,系統資源耗盡,例如:不斷建立線程,不斷髮起網絡鏈接ios

經過jprofer觀察全部對象,觸發gc後觀察變化。獲得不斷遞增的對象找到問題點。web

https://my.oschina.net/u/3705388/blog/1611985

 

經過命令排查算法

確認是否是內存自己就分配太小數據庫

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

致使棧溢出的緣由不少,提三個主要的:

  • java代碼寫得不當,好比出現遞歸死循環,這也是最多見的,只能靠寫代碼的人當心了
  • native代碼有棧上分配的邏輯,而且要求的內存還不小
  • 線程棧空間設置比較小

https://mp.weixin.qq.com/s/1d8W-eyzsnGDr9-uSfag6Q

 

解決CPU佔用太高?

根據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

 

有哪些常見的垃圾收集算法?

  • 標記-清除算法:首先標記出全部須要回收的對象,而後統一回收全部被標記的對象;缺點是效率不高且容易產生大量不連續的內存碎片;
  • 複製算法:將可用內存分爲大小相等的兩塊,每次只使用其中一塊;當這一塊用完了,就將還活着的對象複製到另外一塊上,而後把已使用過的內存清理掉。在HotSpot裏,考慮到大部分對象存活時間很短,將內存分爲Eden和兩塊Survivor,默認比例爲8:1:1。代價是存在部份內存空間浪費,且可能存在空間不夠須要分配擔保的狀況,因此適合在新生代使用;
  • 標記-整理算法:首先標記出全部須要回收的對象,而後讓全部存活的對象都向一端移動,而後直接清理掉端邊界之外的內存。適用於老年代。
  • 分代收集算法:通常把Java堆分新生代和老年代,在新生代用複製算法,在老年代用標記-清理或標記-整理算法,是現代虛擬機一般採用的算法。

 

CMS收集器

  • 是一種以獲取最短回收停頓時間爲目標的收集器,特別適合互聯網站或者B/S的服務端;
  • 它是基於標記-清除 算法實現的,主要包括4個步驟:初始標記(STW,只是初始標記一下GC Roots能直接關聯到的對象,速度很快)、併發標記(非STW,執行GC RootsTracing,耗時比較長)、從新標記(STW,修正併發標記期間因用戶程序繼續致使變更的那一部分對象標記)和併發清除(非STW,耗時較長);
  • 還有3個明顯的缺點:CMS收集器對CPU很是敏感(佔用部分線程及CPU資源,影響總吞吐量)、沒法處理浮動垃圾(默認達到92%就觸發垃圾回收)、大量內存碎片產生(能夠經過參數啓動壓縮);

 

G1收集器

  • 一款面向服務端應用的垃圾收集器,後續會替換掉CMS垃圾收集器;
  • 特色:
並行與併發(充分利用多核多CPU縮短STW時間)
分代收集(獨立管理整個Java堆,但針對不一樣年齡的對象採起不一樣的策略)
空間整合(局部看是基於複製算法,從總體來看是基於標記-整理算法,都不會產生內存碎片)
可預測的停頓(能夠明確指定在一個長度爲M毫秒的時間片內垃圾收集不會超過N毫秒)
  • 將堆分爲大小相等的獨立區域,避免全區域的垃圾收集;新生代和老年代再也不物理隔離,只是部分Region的集合;
  • G1跟蹤各個Region垃圾堆積的價值大小,在後臺維護一個優先列表,根據容許的收集時間優先回收價值最大的Region;
  • Region之間的對象引用以及其餘收集器中的新生代與老年代之間的對象引用,採用Remembered Set來避免全堆掃描;
  • 分爲幾個步驟,和CMS的過程比較相似:
初始標記(標記一下GC Roots能直接關聯的對象並修改TAMS值,須要STW但耗時很短)
併發標記(從GC Root從堆中對象進行可達性分析找存活的對象,耗時較長但能夠與用戶線程併發執行)
最終標記(爲了修正併發標記期間產生變更的那一部分標記記錄,這一期間的變化記錄在Remembered 
Set Log裏,而後合併到Remembered Set裏,該階段須要STW可是可並行執行)
篩選回收(對各個Region回收價值排序,根據用戶指望的GC停頓時間制定回收計劃來回收);

 

g1 和 cms 區別,吞吐量優先和響應優先的垃圾收集器選擇

CMS是一種以最短停頓時間爲目標的收集器

響應優先選擇CMS,吞吐量高選擇G1

 

JDK8:PermGen變動爲MetaSpace詳解

http://blog.csdn.net/lk7688535/article/details/51767460

 

 

 

java 堆內與堆外內存;java的棧內存和堆內存 (堆外內存)

http://blog.csdn.net/u012969412/article/details/76614988

 

 

 

如何進行性能調優以及經常使用的JDK的命令行工具備哪些?

  • JVM調優:CPU使用率與Load值偏大(Thread count以及GC count)、關鍵接口響應時間很慢(GC time以及GC log中的STW的時間)、發生Full GC或者Old CMS GC很是頻繁(內存泄露);
  • JVM停頓(儘可能避免Full GC、關閉偏向鎖、輸出GC日誌到內存文件系統、關閉JVM輸出的jstat日誌);
  • 將Java性能優化分爲4個層級:應用層、數據庫層、框架層、JVM層。每層優化難度逐級增長,涉及的知識和解決的問題也會不一樣。好比應用層須要理解代碼邏輯,經過Java線程棧定位有問題代碼行等;數據庫層面須要分析SQL、定位死鎖等;框架層須要懂源代碼,理解框架機制;JVM 層須要對GC的類型和工做機制有深刻了解,對各類 JVM 參數做用瞭然於胸;
  • 圍繞Java性能優化,有兩種最基本的分析方法:現場分析法和過後分析法。現場分析法經過保留現場,再採用診斷工具分析定位。現場分析對線上影響較大,部分場景不太合適。過後分析法須要儘量多收集現場數據,而後當即恢復服務,同時針對收集的現場數據進行過後分析和復現。
  • OS 的診斷主要關注的是 CPU、Memory、I/O 三個方面。top、vmstat、 free –m、iostat;經常使用的Java應用診斷包括線程、堆棧、GC 等方面的診斷,可使用jstack 、jstat、jmap;

 

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

相關文章
相關標籤/搜索