自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

沒有監(jiān)控過JVM內(nèi)存的職場(chǎng)生涯,是不完美的

云計(jì)算 虛擬化
這篇文章就基于一款JDK自帶的工具(VisualVM),然后編寫內(nèi)存溢出的案例,帶大家體驗(yàn)一下JVM分析的入門。文中涉及到多個(gè)知識(shí)點(diǎn)的融合與實(shí)戰(zhàn)經(jīng)驗(yàn)分享,讀者可留意一下。

[[393678]]

本文轉(zhuǎn)載自微信公眾號(hào)「程序新視界」,作者丑胖俠二師兄。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序新視界公眾號(hào)。

前言

如果你從事Java開發(fā)多年,還沒用過JVM分析工具,還沒嘗試著通過對(duì)JVM的dump日志來進(jìn)行故障定位和性能調(diào)優(yōu),那么可以說是你職場(chǎng)生涯中的一大遺憾,也是一種能力的缺失。

這篇文章就基于一款JDK自帶的工具(VisualVM),然后編寫內(nèi)存溢出的案例,帶大家體驗(yàn)一下JVM分析的入門。文中涉及到多個(gè)知識(shí)點(diǎn)的融合與實(shí)戰(zhàn)經(jīng)驗(yàn)分享,讀者可留意一下。

VisualVM簡(jiǎn)介

VisualVM是Netbeans的profile子項(xiàng)目,在JDK6.0 update 7 中自帶,能夠監(jiān)控線程,內(nèi)存情況,查看方法的CPU時(shí)間和內(nèi)存中的對(duì)象,已被GC的對(duì)象,反向查看分配的堆棧(如100個(gè)String對(duì)象分別由哪幾個(gè)對(duì)象分配出來的)。

如果已經(jīng)正確配置classpath路徑,VisualVM的啟動(dòng)非常簡(jiǎn)單,只需在命令行輸入jvisualvm即可啟動(dòng)圖形化界面。VisualVM不僅支持本機(jī)監(jiān)控,還支持遠(yuǎn)程監(jiān)控。

遠(yuǎn)程監(jiān)控配置稍微復(fù)雜一些,這里以本地監(jiān)控為示例進(jìn)行演示。至于生產(chǎn)環(huán)境,可選擇遠(yuǎn)程監(jiān)控,也可配合jmap先生成dump文件,然后下載dump文件進(jìn)行分析。

VisualVM功能界面

啟動(dòng)VisualVM之后,先來看一下有助于JVM分析的幾項(xiàng)功能。這里先以本地啟動(dòng)的Idea為例來進(jìn)行展示。

概述

進(jìn)入VisualVM之后,點(diǎn)擊左邊的對(duì)應(yīng)進(jìn)程,首先展示的是【概述】?jī)?nèi)容:

概述中顯示了JVM、Java版本、dump批次等信息,在實(shí)戰(zhàn)中這里的信息可用來進(jìn)行信息核對(duì)。特別是JVM參數(shù)和系統(tǒng)屬性項(xiàng)的核對(duì)。

曾遇到一個(gè)場(chǎng)景,就是通過啟動(dòng)Java程序時(shí)JVM參數(shù)的位置寫錯(cuò)了,導(dǎo)致JVM參數(shù)并不生效。

比如如下指令,由于JVM的參數(shù)寫在了最后,會(huì)導(dǎo)致參數(shù)設(shè)置無(wú)效。

  1. java -jar app.jar -Xms256m -Xmx512m 

而正確的寫法應(yīng)該是如下:

  1. java -Xms256m -Xmx512m  -jar app.jar 

上面這種情況,通過該工具可以輕易的看出JVM參數(shù)項(xiàng)里面并沒有指定的參數(shù)值。

監(jiān)視

監(jiān)視界面是用的比較多的一個(gè)界面,通過該界面可以查看CPU使用情況、堆和Metaspace的使用情況、線程的使用情況、類的加載情況等。

通過對(duì)堆和Metaspace的使用情況分析,可以看到對(duì)應(yīng)內(nèi)存空間的使用和增長(zhǎng)情況,可進(jìn)行合理調(diào)整和規(guī)劃。

點(diǎn)擊右上角的“堆 dump”,會(huì)基于點(diǎn)擊的時(shí)間節(jié)點(diǎn)生成dump文件。

概要部分會(huì)顯示生成dump文件的時(shí)間節(jié)點(diǎn)和存儲(chǔ)路徑。我們用來分析內(nèi)存主要是在此頁(yè)面中的“類”菜單內(nèi)。

進(jìn)入可查看在堆中不同實(shí)例占用的內(nèi)存大小。雙擊類名,即可進(jìn)入查看“實(shí)例數(shù)”,也就是具體類的實(shí)例詳情。

而我們?cè)趦?nèi)存分析時(shí)最重要的其實(shí)就是“類”的數(shù)量。在了解了上述的基本操作之后,我們就用一個(gè)實(shí)例來模擬分析一下內(nèi)存溢出的場(chǎng)景吧。

內(nèi)存溢出場(chǎng)景構(gòu)建

先寫一段代碼,用來模擬內(nèi)存溢出,也就是創(chuàng)建一個(gè)Map,然后向其中不斷的新增對(duì)象。同時(shí)在程序處理的過程中讓線程睡眠或死循環(huán)來方便通過VisualVM進(jìn)行查看。

測(cè)試代碼如下:

  1. public class MemoryLeakTest { 
  2.  
  3.     /** 
  4.      * 聲明緩存對(duì)象 
  5.      */ 
  6.     private static final Map<String, TestMemory> CACHE_MAP = new HashMap<>(); 
  7.  
  8.     public static void main(String[] args) { 
  9.         try { 
  10.             //給打開visualVm時(shí)間 
  11.             Thread.sleep(10000); 
  12.         } catch (InterruptedException e) { 
  13.             e.printStackTrace(); 
  14.         } 
  15.         //循環(huán)添加對(duì)象到緩存 
  16.         for (int i = 0; i < 1000000; i++) { 
  17.             TestMemory t = new TestMemory(); 
  18.             CACHE_MAP.put("key" + i, t); 
  19.         } 
  20.         System.out.println("-------1------"); 
  21.         //為dump出堆提供時(shí)間 
  22.         try { 
  23.             //給打開visualVm時(shí)間 
  24.             Thread.sleep(10000); 
  25.         } catch (InterruptedException e) { 
  26.             e.printStackTrace(); 
  27.         } 
  28.  
  29.         for(int i=0; i<1000000;i++){ 
  30.             TestMemory t = new TestMemory(); 
  31.             CACHE_MAP.put("key"+i,t); 
  32.         } 
  33.     } 

TestMemory類代表生成中的業(yè)務(wù)類。

  1. public class TestMemory { 

為了讓程序更快的達(dá)到內(nèi)存的閾值,我們啟動(dòng)時(shí)可限制JVM的大小,這里設(shè)置為:

  1. -Xms128m -Xmx128m 

另外,為了分析堆的內(nèi)存結(jié)構(gòu)中每個(gè)區(qū)域(新生代、老年代)的內(nèi)存使用情況,可在VisualVM的“工具”、“插件”中安裝Visual GC插件。該插件的使用后續(xù)會(huì)看到效果。

一切準(zhǔn)備妥當(dāng),下面來進(jìn)行驗(yàn)證。

內(nèi)存溢出分析

下面我們就來啟動(dòng)程序,啟動(dòng)VisualVM來進(jìn)行內(nèi)存溢出的分析。

當(dāng)程序執(zhí)行的過程中,我們會(huì)發(fā)現(xiàn)“堆”內(nèi)存會(huì)出現(xiàn)一個(gè)快速增加的曲線。

這個(gè)過程中Metaspace也在隨之增長(zhǎng)。

打開Visual GC界面,我們會(huì)看到面試中被問過很多遍的堆內(nèi)存結(jié)構(gòu):

通過這張圖,可以直觀的看到堆內(nèi)存中的老年代、新生代、Metaspace空間(JDK8),還有新生代中的Eden、S0(Survivor From)、S1(Survivor To),而且它們的分配比例也有一個(gè)比較直觀的展示。通過這種形式,是不是可以更直觀的學(xué)習(xí)堆內(nèi)存結(jié)構(gòu)呢?

這里Eden已經(jīng)被填滿、S0和S1為空,老年代也幾乎被填滿(因?yàn)槔占療o(wú)法清除持有引用的對(duì)象)。

最重要的是你會(huì)發(fā)現(xiàn)針對(duì)老年代在20分鐘內(nèi)進(jìn)行了3850次垃圾回收。也就是說已經(jīng)觸發(fā)了頻繁的Full GC操作,而且內(nèi)存并沒有被釋放掉。在生產(chǎn)系統(tǒng)中,當(dāng)你看到系統(tǒng)在頻繁的進(jìn)行Full GC操作,那是JVM在釋放一個(gè)很恐怖的信號(hào)了。

上面說了一些表象的內(nèi)容,現(xiàn)在真正開進(jìn)行內(nèi)存分析了。回到上面提到的“監(jiān)視”、“堆dump”、“類”中,可以看到下圖:

可以看到,堆中存在著100萬(wàn)個(gè)TestMemory對(duì)象。當(dāng)你看到堆中有類似的大量的對(duì)象存在,你應(yīng)該意識(shí)到此處可能有內(nèi)存泄露。也就是大量的對(duì)象被創(chuàng)建,而沒有被“順利”回收。我們這里沒被回收的原因是對(duì)象被放在了靜態(tài)變量里面了。

上面已經(jīng)提到,你還可以進(jìn)一步雙擊對(duì)象名稱,去查看對(duì)象的詳細(xì)信息。

通過上面步驟,基本上可以定位到哪些對(duì)象的處理出現(xiàn)了問題,此時(shí)再回到代碼中針對(duì)相應(yīng)的代碼進(jìn)行排查,便可快速定位內(nèi)存溢出的問題所在。其中我們需要特別留意上述過程中VisualVM為我們提供的那些報(bào)警信號(hào)和數(shù)據(jù)呈現(xiàn)。

小結(jié)

本文我們是在講VisualVM的使用,也是在講線上JVM的排查,也是在講JVM的內(nèi)存結(jié)構(gòu),還是在講如何去構(gòu)造一個(gè)內(nèi)存溢出(bug)的場(chǎng)景。但講什么并不重要,關(guān)鍵是看,通過這篇文章,你重溫了什么,學(xué)到了什么,又收獲了什么。

 

責(zé)任編輯:武曉燕 來源: 程序新視界
相關(guān)推薦

2009-09-11 09:36:53

李開復(fù)

2022-03-29 08:55:18

存儲(chǔ)引擎核心

2022-03-02 09:49:14

Rust編程語(yǔ)言

2010-06-18 10:51:27

NetBeans 6.CSSEclipse

2012-12-21 15:16:27

新浪微博小米

2018-10-22 14:00:12

數(shù)據(jù)數(shù)據(jù)插補(bǔ)數(shù)據(jù)科學(xué)

2019-05-15 11:38:22

GoogleGo編程語(yǔ)言

2019-04-17 13:34:30

Galaxy Fold三星折疊屏

2010-09-26 14:55:46

JVM內(nèi)存監(jiān)控

2010-08-30 10:53:10

職場(chǎng)

2012-03-02 14:20:46

JavaJVM

2020-10-23 10:36:08

Dropbox

2020-10-26 09:53:44

Dropbox攻擊網(wǎng)絡(luò)安全

2022-04-13 15:04:38

模型理論方案

2010-08-05 16:26:09

職場(chǎng)升職計(jì)

2014-06-17 09:13:34

下一代防火墻NGFW

2017-09-11 10:09:59

刪庫(kù)DBA淘汰

2019-05-15 09:00:00

決策樹機(jī)器學(xué)習(xí)人工智能

2017-03-10 16:32:44

Apache Spar大數(shù)據(jù)工具

2022-02-15 12:14:49

人工智能數(shù)據(jù)優(yōu)化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)