visualvm远程监控jvm_大型企业JVM实战:优化及面试热点分析
本次課程的筆記非常多,而且內(nèi)容已經(jīng)整理了好幾個小時了,接著下來內(nèi)容也會更多,也是大型企業(yè)JVM性能調(diào)優(yōu)實戰(zhàn)的最后一節(jié),希望對你有幫助!
04:JVM性能監(jiān)控與故障處理工具?
大型企業(yè)JVM性能調(diào)優(yōu)實戰(zhàn)之總結(jié)
17:JVM性能監(jiān)控與故障處理工具-javap
目標
掌握和了解javap的語法
分析
javap的用法格式:javap<options>
其中classes就是你要反編譯的class文件。在命令行中直接輸入javap或javap -help可以看到j(luò)avap的options有如下選項:?
-help --help -? 輸出此用法消息-version 版本信息,其實是當前javap所在jdk的版本信息,不是class在哪個jdk下生成的。-v -verbose 輸出附加信息(包括行號、本地變量表,反匯編等詳細信息)-l 輸出行號和本地變量表-public 僅顯示公共類和成員-protected 顯示受保護的/公共類和成員-package 顯示程序包/受保護的/公共類 和成員(默認)-p -private 顯示所有類和成員-c 對代碼進行反匯編-s 輸出內(nèi)部類型簽名-sysinfo 顯示正在處理的類的系統(tǒng)信息 (路徑,大小, 日期, MD5 散列)-constants 顯示靜態(tài)最終常量-classpath 指定查找用戶類文件的位置-bootclasspath 覆蓋引導(dǎo)類文件的位置詳細查看:https://www.jianshu.com/p/6a8997560b05?
18:JVM性能監(jiān)控與故障處理工具-jps
目標
掌握和了解jps的使用
分析
jps(Java Virtual Machine Process Status Tool) 顯示當前所有的java進程pid的命令。語法是:?
19:JVM性能監(jiān)控與故障處理工具-jstat
目標
掌握和了解jstat的使用
分析
jstat是監(jiān)視Java虛擬機(JVM)統(tǒng)計信息
用于監(jiān)視虛擬機各種運行狀態(tài)信息的命令行工具,如:類裝載、內(nèi)存、垃圾收集,是在沒有圖形頁面純文本控制臺中定位運行期虛擬機性能問題的首選工具?
命令格式:jstat [options vmid [interval[s|ms][count]]]如:jstat -gc 2764 250 20(每隔250毫秒查詢一次進程2764的垃圾收集情況,一共查詢20次)?
jinfo:java配置信息工具?
用于實時的查看和調(diào)整虛擬機各項參數(shù)命令格式:jinfo [option] vmidjinfo -flags 2734查看2723虛擬機的所有參數(shù)jmap:java內(nèi)存映像工具?
用于生成堆轉(zhuǎn)儲快照,一般稱為heapdump 或 dump文件,如果不使用jmap命令 也很暴力的通過:-XX:+HeapDumpOnOutOfMemoryError參數(shù),可以讓虛擬機出現(xiàn)OOM異常之后自動生成dump文件。命令格式:jmap [option] vmid//將904虛擬機的內(nèi)存映像存儲到當前文件夾的ddd.hprof文件中jmap?-dump:format=b,file=ddd.hprof?904jhat:虛擬機堆轉(zhuǎn)儲快照分析工具
與jmap搭配使用,用于分析dump文檔,內(nèi)置了http服務(wù)器,可以在瀏覽器中進行分析jstack:java堆棧跟蹤工具?
用于生成虛擬機當前時刻的線程快照,線程快照就是當前虛擬機內(nèi)每一條線程正在執(zhí)行的方法堆棧的集合。用于分析線程死鎖、死循環(huán)、請求外部資源時間過長等常見原因20:JVM性能優(yōu)化-CPU飆高排查實戰(zhàn)?
項目準備:
在linux系統(tǒng)模擬生產(chǎn)環(huán)境
通過 nohup java -jar 項目jar.jar > 日志文件 & 啟動項目?
項目準備:在linux系統(tǒng)模擬生產(chǎn)環(huán)境通過 nohup java -jar 項目jar.jar > 日志文件 & 啟動項目1、jps 查看進程
2、訪問項目即可http://192.168.153.176:8767/loop 訪問以后直接離開,其實后臺的進程在死循環(huán)執(zhí)行,這個時候需要排查
3、使用top命令查看內(nèi)存情況 .得到內(nèi)存高的進程ID?
4、top -p pid -H?
top -p 2746 -H5、查看最高的線程PID 因為是十進制的 需要進行16進制的轉(zhuǎn)換
#printf "%x" pid> printf "%x" 2764acc6、jstack pid > pid.log?
> jstack 2746 > pid.log/線程ID 模糊查詢
線程的狀態(tài)是Runnable 代表線程正在運行?
21:JVM性能優(yōu)化-死鎖排查實戰(zhàn)
1:重新啟動項目
2:瀏覽器訪問:http://192.168.153.176:8767/deadlock
3:jstack pid 排查死鎖。結(jié)果如下:?
上面也很清楚的看到問題出現(xiàn)的方法和那兩個線程出現(xiàn)的問題和原因。
JDK的可視化工具?
JDK除了提供大量的命令行工具外,還有兩個功能強大的可視化工具:JConsole 和 VisualVM ,這兩個工具是JDK的正式成員,功能非常強大!jconsole:Java監(jiān)視與管理控制臺?
通過jdk/bin目錄下的 jconsole.exe啟動JConsole,將會自動的搜索出本機的所有java虛擬機進程?
在本地進程中會列出本地 正在運行的java虛擬機列表,也可以遠程連接其他服務(wù)器的java服務(wù)器,現(xiàn)在我們選擇JConsoleTest1的進程,并且將堆的大小固定在100MB, 每個隔一小段時間向集合中裝入128KB的數(shù)據(jù),并注意JConsole監(jiān)控中個數(shù)據(jù)指標的變化。?
/*** VM Args: -Xms100m -Xmx100m -XX:+UseSerialGC**/public class JConsoleTest1 {static class OOMObject{public byte[] placeholder = newbyte[128*1024];}public static void fillHeap(int num) throwsInterruptedException {List list = newArrayList();for (int i = 0; i < num; i++) {Thread.sleep(100);list.add(new OOMObject());}System.gc();Thread.sleep(5000);}public static void main(String[] args) throwsInterruptedException {fillHeap(500);fillHeap(1000);}}VisualVM:多合一故障處理工具
All in One Java Troubleshooting Tool ,目前為止JDK發(fā)布的最強大的運行監(jiān)視和故障處理程序,除了基本的運行監(jiān)視、故障處理之外,它還設(shè)計了可插拔的插件功能,可以根據(jù)需要添加一些優(yōu)秀的插件時間更強大的功能。它的性能分析功能甚至比一些專業(yè)的收費工具也不遜色。
雙擊JDK/bin目錄下的 jvisualvm.exe,啟動VisualVM工具
左側(cè)列表顯示的是本地java虛擬機的活動列表,點擊一個進程可以進入監(jiān)控狀態(tài)概述頁簽展示了 當前監(jiān)控java虛擬機的配置信息?
監(jiān)視頁簽展示了,CPU 類加載 堆 線程的基本監(jiān)控信息
線程的信息,可以轉(zhuǎn)儲線程快照,也可以打開線程快照進行分析?
遠程連接監(jiān)控
05:JVM調(diào)優(yōu)案例分析與解決思路
大型企業(yè)JVM性能調(diào)優(yōu)實戰(zhàn)之java的技術(shù)體系
案例分析
1.高性能硬件上的程序部署策略
一個15萬 PV/天左右的在線文檔類型網(wǎng)站最近更換了硬件設(shè)備:4個CPU、16G物理內(nèi)存 操作系統(tǒng)為64位的Centos6.5的系統(tǒng)使用Tomcat作為服務(wù)器,所有硬件資源全部給這個不太大的網(wǎng)站使用,為了更好的使用硬件資源 選用了64位的JDK 并且通過 -Xmx 和 -Xms 參數(shù)將java堆固定在12GB.使用一段時間后發(fā)現(xiàn)效果仍不理想,網(wǎng)站會經(jīng)常不定期的出現(xiàn)長時間失去響應(yīng)的情況。使用監(jiān)控工具監(jiān)控發(fā)現(xiàn),網(wǎng)站失去響應(yīng)是由于Full GC造成的,虛擬機運行在Server模式下默認采用的是吞吐量優(yōu)先的垃圾收集器,回收12G的堆 ,一次Full GC達14秒, 由于程序設(shè)計的關(guān)系,訪問文檔時要把文檔從磁盤提取到內(nèi)存系統(tǒng)中,導(dǎo)致內(nèi)存中出現(xiàn)很多由文檔序列化產(chǎn)生的大對象,這些大對象很多都進入了老年代,沒有在新生代GC中清理掉,這種情況下雖然有12GB的堆,內(nèi)存也很快被耗盡,由此導(dǎo)致每隔10多分鐘出現(xiàn)一次10多秒中的無響應(yīng)狀態(tài)。調(diào)優(yōu)方案:這種需要經(jīng)常解析大對象到內(nèi)存的情況,再大的堆也會很快裝滿最終采用 5臺 32位虛擬機部署Tomcat集群的方式。每個tomcat設(shè)置的堆 為1.5GB,回收停頓時間大大降低另外建立了一個Nginx服務(wù)器將靜態(tài)資源進行分離,大大減少Tomcat的處理請求數(shù)文檔服務(wù)器的壓力主要集中在磁盤和內(nèi)存訪問,對CPU的敏感度較低,因此將垃圾收集器替換為CMS并發(fā)收集器大大利用了多核硬件的并發(fā)優(yōu)勢。部署方式調(diào)整后,服務(wù)沒有在出現(xiàn)長時間的停頓,速度較之前有較大提升2.堆外內(nèi)存導(dǎo)致的溢出錯誤
一個中小型的電子考試系統(tǒng) ,為了實現(xiàn)客戶端能實時的從服務(wù)器獲取考試數(shù)據(jù),系統(tǒng)使用了逆向AJAX技術(shù),選用了CometD作為服務(wù)端推送框架,服務(wù)器內(nèi)存為 8GB,運行在32位windows操作系統(tǒng)。測試期間發(fā)現(xiàn)服務(wù)器不定期會出現(xiàn)內(nèi)存溢出異常,32位的系統(tǒng)堆最多就1.6GB左右,在大也沒什么效果。采用監(jiān)控工具監(jiān)測堆中GC情況,發(fā)現(xiàn)GC并不頻繁,各分代都顯示內(nèi)存穩(wěn)定。最后,因為是不定期內(nèi)存溢出,管理員等待溢出后查看Tomcat中的日志 發(fā)現(xiàn)異常顯示為OutOfMemoryError:null在錯誤列表中Unsafe.allocationMemoryjava.nio.DirectByteBuffer后經(jīng)過排查,原來是在直接內(nèi)存中溢出的,雖然垃圾收集會對直接內(nèi)存進行回收,但直接內(nèi)存只能等待老年代在進行fullGC的時候順便幫它回收一下,如果回收完一次 很快空間又滿了,只能眼睜睜看著堆內(nèi)還有很多內(nèi)存空間,也只能報異常了。Nio框架的操作會使用到直接內(nèi)存。解決方案:最終通過 -XX:MaxDirectMemorySize 調(diào)大了直接內(nèi)存的大小解決了問題3.執(zhí)行外部命令導(dǎo)致系統(tǒng)緩慢
4.不恰當?shù)臄?shù)據(jù)結(jié)構(gòu)到時內(nèi)存占用過大
調(diào)優(yōu)技巧匯總
大型企業(yè)JVM性能調(diào)優(yōu)實戰(zhàn)之jvm優(yōu)化和tomcat優(yōu)化
JVM相關(guān)面試題匯總?
說一下 JVM 的主要組成部分?及其作用??
類加載器(ClassLoader)運行時數(shù)據(jù)區(qū)(Runtime Data Area)執(zhí)行引擎(Execution Engine)本地庫接口(Native Interface)組件的作用:首先通過類加載器(ClassLoader)會把 Java 代碼轉(zhuǎn)換成字節(jié)碼,運行時數(shù)據(jù)區(qū)(Runtime Data Area)再把字節(jié)碼加載到內(nèi)存中,而字節(jié)碼文件只是 JVM 的一套指令集規(guī)范,并不能直接交給底層操作系統(tǒng)去執(zhí)行,因此需要特定的命令解析器執(zhí)行引擎(Execution Engine),將字節(jié)碼翻譯成底層系統(tǒng)指令,再交由 CPU 去執(zhí)行,而這個過程中需要調(diào)用其他語言的本地庫接口(Native Interface)來實現(xiàn)整個程序的功能說一下 JVM 運行時數(shù)據(jù)區(qū)?詳細介紹下每個區(qū)域的作用??
不同虛擬機的運行時數(shù)據(jù)區(qū)可能略微有所不同,但都會遵從 Java 虛擬機規(guī)范, Java 虛擬機規(guī)范規(guī)定的區(qū)域分為以下 5 個部分:程序計數(shù)器(Program Counter Register):當前線程所執(zhí)行的字節(jié)碼的行號指示器,字節(jié)碼解析器的工作是通過改變這個計數(shù)器的值,來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復(fù)等基礎(chǔ)功能,都需要依賴這個計數(shù)器來完成;Java 虛擬機棧(Java Virtual Machine Stacks):用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息;本地方法棧(Native Method Stack):與虛擬機棧的作用是一樣的,只不過虛擬機棧是服務(wù) Java 方法的,而本地方法棧是為虛擬機調(diào)用 Native方法服務(wù)的;Java 堆(Java Heap):Java 虛擬機中內(nèi)存最大的一塊,是被所有線程共享的,幾乎所有的對象實例都在這里分配內(nèi)存;方法區(qū)(Methed Area):用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯后的代碼等數(shù)據(jù)。說一下堆棧的區(qū)別??
功能方面:堆是用來存放對象的,棧是用來執(zhí)行程序的。共享性:堆是線程共享的,棧是線程私有的。空間大小:堆大小遠遠大于棧。java中都有哪些類加載器?
啟動類加載器(Bootstrap ClassLoader),是虛擬機自身的一部分,用來加載Java_HOME/lib/目錄中的,或者被 -Xbootclasspath 參數(shù)所指定的路徑中并且被虛擬機識別的類庫;其他類加載器:擴展類加載器(Extension ClassLoader):負責加載\lib\ext目錄或Java. ext. dirs系統(tǒng)變量指定的路徑中的所有類庫;應(yīng)用程序類加載器(Application ClassLoader)。負責加載用戶類路徑(classpath)上的指定類庫,我們可以直接使用這個類加載器。一般情況,如果我們沒有自定義類加載器默認就是用這個加載器。什么是雙親委派模型??
如果一個類加載器收到了類加載的請求,它首先不會自己去加載這個類,而是把這個請求委派給父類加載器去完成,每一層的類加載器都是如此,這樣所有的加載請求都會被傳送到頂層的啟動類加載器中,只有當父加載無法完成加載請求(它的搜索范圍中沒找到所需的類)時,子加載器才會嘗試去加載類。說一下類裝載的執(zhí)行過程?
類裝載分為以下 5 個步驟:加載:根據(jù)查找路徑找到相應(yīng)的 class 文件然后導(dǎo)入;檢查:檢查加載的 class 文件的正確性;準備:給類中的靜態(tài)變量分配內(nèi)存空間;解析:虛擬機將常量池中的符號引用替換成直接引用的過程。符號引用就理解為一個標示,而在直接引用直接指向內(nèi)存中的地址;初始化:對靜態(tài)變量和靜態(tài)代碼塊執(zhí)行初始化工作。怎么判斷對象是否可以被回收??
一般有兩種方法來判斷:引用計數(shù)器:為每個對象創(chuàng)建一個引用計數(shù),有對象引用時計數(shù)器 +1,引用被釋放時計數(shù) -1,當計數(shù)器為 0 時就可以被回收。它有一個缺點不能解決循環(huán)引用的問題;可達性分析:從 GC Roots 開始向下搜索,搜索所走過的路徑稱為引用鏈。當一個對象到 GC Roots 沒有任何引用鏈相連時,則證明此對象是可以被回收的。Java 中都有哪些引用類型??
強引用:發(fā)生 gc 的時候不會被回收。軟引用:有用但不是必須的對象,在發(fā)生內(nèi)存溢出之前會被回收。弱引用:有用但不是必須的對象,在下一次GC時會被回收。虛引用(幽靈引用/幻影引用):無法通過虛引用獲得對象,用PhantomReference 實現(xiàn)虛引用,虛引用的用途是在 gc 時返回一個通知。說一下 JVM 有哪些垃圾回收算法??
標記-清除算法:標記無用對象,然后進行清除回收。缺點:效率不高,無法清除垃圾碎片。標記-整理算法:標記無用對象,讓所有存活的對象都向一端移動,然后直接清除掉端邊界以外的內(nèi)存。復(fù)制算法:按照容量劃分二個大小相等的內(nèi)存區(qū)域,當一塊用完的時候?qū)⒒钪膶ο髲?fù)制到另一塊上,然后再把已使用的內(nèi)存空間一次清理掉。缺點:內(nèi)存使用率不高,只有原來的一半。分代算法:根據(jù)對象存活周期的不同將內(nèi)存劃分為幾塊,一般是新生代和老年代,新生代基本采用復(fù)制算法,老年代采用標記整理算法。說一下 JVM 有哪些垃圾回收器??
Serial:最早的單線程串行垃圾回收器。Serial Old:Serial 垃圾回收器的老年版本,同樣也是單線程的,可以作為 CMS 垃圾回收器的備選預(yù)案。ParNew:是 Serial 的多線程版本。Parallel 和 ParNew 收集器類似是多線程的,但 Parallel 是吞吐量優(yōu)先的收集器,可以犧牲等待時間換取系統(tǒng)的吞吐量。Parallel Old 是 Parallel 老生代版本,Parallel 使用的是復(fù)制的內(nèi)存回收算法,Parallel Old 使用的是標記-整理的內(nèi)存回收算法。CMS:一種以獲得最短停頓時間為目標的收集器,非常適用 B/S 系統(tǒng)。G1:一種兼顧吞吐量和停頓時間的 GC 實現(xiàn),是 JDK 9 以后的默認 GC選項。新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么區(qū)別??
- 新生代回收器:Serial、ParNew、Parallel Scavenge- 老年代回收器:Serial Old、Parallel Old、CMS- 整堆回收器:G1新生代垃圾回收器一般采用的是復(fù)制算法,復(fù)制算法的優(yōu)點是效率高,缺點是內(nèi)存利用率低;老年代回收器一般采用的是標記-整理的算法進行垃圾回收。簡述分代垃圾回收器是怎么工作的??
分代回收器有兩個分區(qū):老生代和新生代,新生代默認的空間占比總空間的1/3,老生代的默認占比是 2/3。新生代使用的是復(fù)制算法,新生代里有 3 個分區(qū):Eden、ToSurvivor、From Survivor,它們的默認占比是 8:1:1,它的執(zhí)行流程如下:把 Eden + From Survivor 存活的對象放入 To Survivor 區(qū);清空 Eden 和 From Survivor 分區(qū);From Survivor 和 To Survivor 分區(qū)交換,From Survivor 變To Survivor,To Survivor 變 From Survivor。每次在 From Survivor 到 To Survivor 移動時都存活的對象,年齡就 +1,當年齡到達 15(默認配置是 15)時,升級為老生代。大對象也會直接進入老生代。老生代當空間占用到達某個值之后就會觸發(fā)全局垃圾收回,一般使用標記整理的執(zhí)行算法。以上這些循環(huán)往復(fù)就構(gòu)成了整個分代垃圾回收的整體執(zhí)行流程。Minor GC與Full GC分別在什么時候發(fā)生?
新生代內(nèi)存不夠用時候發(fā)生MGC也叫YGC,JVM內(nèi)存不夠的時候發(fā)生FGC說一下 JVM 調(diào)優(yōu)的工具??
JDK 自帶了很多監(jiān)控工具,都位于 JDK 的 bin 目錄下,其中最常用的是jconsole 和 jvisualvm 這兩款視圖監(jiān)控工具。jconsole:用于對 JVM 中的內(nèi)存、線程和類等進行監(jiān)控;jvisualvm:JDK 自帶的全能分析工具,可以分析:內(nèi)存快照、線程快照、程序死鎖、監(jiān)控內(nèi)存的變化、gc 變化等常用的 JVM 調(diào)優(yōu)的參數(shù)都有哪些?
-Xms2g:初始化推大小為 2g;-Xmx2g:堆最大內(nèi)存為 2g;-XX:NewRatio=4:設(shè)置年輕的和老年代的內(nèi)存比例為 1:4;-XX:SurvivorRatio=8:設(shè)置新生代 Eden 和 Survivor 比例為8:2;–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器組合;-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器組合;-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器組合;-XX:+PrintGC:開啟打印 gc 信息;-XX:+PrintGCDetails:打印?gc?詳細信息。記得點個在看,或者轉(zhuǎn)發(fā)朋友圈哦!
總結(jié)
以上是生活随笔為你收集整理的visualvm远程监控jvm_大型企业JVM实战:优化及面试热点分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 特斯拉自动驾驶系统秘密,来自特斯拉AI总
- 下一篇: Unicode中文编码表