成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

干貨分享丨jvm系列:dump文件深度分析

開發 后端
java內存dump是jvm運行時內存的一份快照,利用它可以分析是否存在內存浪費,可以檢查內存管理是否合理,當發生OOM的時候,可以找出問題的原因。

JVM dump

java內存dump是jvm運行時內存的一份快照,利用它可以分析是否存在內存浪費,可以檢查內存管理是否合理,當發生OOM的時候,可以找出問題的原因。那么dump文件的內容是什么樣的呢?我們一步一步來

獲取JVM dump文件

獲取dump文件的方式分為主動和被動

i.主動方式:

1.利用jmap,也是最常用的方式:jmap -dump:[live],format=b,file=

2.利用jcmd,jcmd GC.heap_dump

3.使用VisualVM,可以界面操作進行dump內存

4.通過JMX的方式 

  1. MBeanServer server = ManagementFactory.getPlatformMBeanServer();  
  2. HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); 
  3. mxBean.dumpHeap(filePath, live); 

參考(https://www.baeldung.com/java...

ii.被動方式:

被動方式就是我們通常的OOM事件了,通過設置參數-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=

dump文件分析

結構示意圖

結構詳解

dump文件是堆內存的映射,由文件頭和一系列內容塊組成

文件頭

由musk, 版本,identifierSize, 時間4部分組成

1、musk:4個byte,內容為'J', 'A', 'V', 'A'即JAVA

2、version:若干byte,值有以下三種 

  1. " PROFILE 1.0\0",  
  2. " PROFILE 1.0.1\0",  
  3. " PROFILE 1.0.2\0"  

3、identifierSize:4個byte數字,值為4或者8,表示一個引用所占用的byte數

4、time:8個byte,dump文件生成時間

說明:java一個類的成員變量有兩種類型

  1. 基本類型(8種基本類型),它們占用byte數固定不變,每生成一個對象它們就需要給它們賦初始值,分配空間
  2. 是引用類型,表示一個對象,在類中只有一個引用,引用只是一個數值,所占用的空間大小為identifierSize,被引用對象即將在堆中的另一個地方

        例如定義一個類 

  1. public class Person {  
  2.  private int age;//4個byte  
  3.  private String name;//identifierSize個byte  
  4.  private double weight;//8個byte  
  5.  

當我們在new Person()的時候

它就需要申請一個空間,空間大小為 對象頭大小+4+identifierSize+8個byte

對象大小的測量:

jdk提供一個測試對象占用內存大小的工具Instrumentation,但是Instrumentation沒法直接引用到,需要通過agent來引用到

定義一個Premain類, javac Premain.java 

  1. //Premain.java  
  2. public class Premain {  
  3.     public static java.lang.instrument.Instrumentation inst;  
  4.     public static void premain(String args, java.lang.instrument.Instrumentation inst) {  
  5.         Premain.inst = inst;  
  6.     }  
  7.  

編寫一個Manifest文件 

  1. manifest.mf  
  2. Manifest-Version: 1.0  
  3. Premain-Class: Premain  
  4. Can-Redefine-Classes: true  
  5. Can-Retransform-Classes: true  

打包 

  1. jar -cmf manifest.mf premain.jar Premain.class 

定義一個執行類, javac PersonTest.java 

  1. //PersonTest.java  
  2. public class PersonTest {  
  3.     public static void main(String[] args) throws Exception {  
  4.         Class clazz = Class.forName("Premain");  
  5.         if (clazz != null) {  
  6.             Person p = new Person();  
  7.             java.lang.instrument.Instrumentation inst = (java.lang.instrument.Instrumentation)clazz.getDeclaredField("inst").get(null);  
  8.             System.out.println("person size:[" + inst.getObjectSize(p) + "]B");  
  9.             System.out.println("class size:[" + inst.getObjectSize(p.getClass()) + "]B"); 
  10.         }  
  11.     }  
  12.  

帶agent執行 

  1. java -javaagent:premain.jar PersonTest 

結果: 

  1. person size:[32]B  
  2. class size:[504]B  

內容塊

每個塊都是塊頭和塊體組成

塊頭

塊頭由1個byte的塊類型,4個byte的時間time,4個byte的長度表示此內容塊占用byte數

type類型一般有5種,字符串,類,棧楨,棧,及dump塊

  1. 字符串,由identifierSize個byte的字符串id,后面是(length-identifierSize)個byte的字符串內容(后續對字符串是直接引用的這里面的id)
  2. 類,由4個byte的類序列(在棧楨中使用),identifierSize個byte的類id(解析類的時候用到),4個byte的序列id(暫未使用),identifierSize個byte的類名id
  3. 棧楨,由identifierSize個byte的楨id,identifierSize個byte的方法名id,identifierSize個byte的方法標識id,identifierSize個byte的類文件名id,4個byte的類序列,4個byte的行號
  4. 棧,由4個byte的棧序號,4個byte的線程序號,4個byte的楨數量,后面就是若干個identifierSize個byte的楨id
  5. dump塊就是所有對象的內容了,每個對象由1個byte的子類型,和對象內容結成,子類型有6種,gc root, 線程對象,類,對象,基本類型數組,對象數組

gc root

gc root有4種結構,8種類型

  1. identifierSize個byte的對象id,類型有SYSTEM_CLASS,BUSY_MONITOR, 及未UNKNOWN
  2. identifierSize個byte的對象id,4個byte的線程序列號,類型有NATIVE_STACK,THREAD_BLOCK
  3. identifierSize個byte的對象id,4個byte的線程序列號,4個byte的棧楨深度,類型有JAVA_LOCAL,NATIVE_LOCAL
  4. identifierSize個byte的對象id,identifierSize個byte的global refId(暫未使用),類型有NATIVE_STATIC

gc root示意圖

gc root為垃圾收集追溯的源頭,每個gc root都指向一個初始對象,無法追溯的對象是要被回收掉的

系統類,只有classLoader為null的類才是gc root,每個類都是一個gc root

線程棧,線程中方法參數,局部變量都是gc root,每個對象都是一個gc root

系統保留對象,每個對象都是一個gc root

類對象

1、基本信息:

  1. identifierSize個byte的類對象id
  2. 4個byte的棧序列號,
  3. identifierSize個byte的父類對象id,
  4. identifierSize個byte的classLoader對象id,
  5. identifierSize個byte的Signer對象id,
  6. identifierSize個byte的protection domain對象id,
  7. identifierSize個byte的保留id1和id2,
  8. 4個byte的類實例對象大小,
  9. 2個byte的常量個數,后面是每個常量的,2個byte的下標,1個byte的常量類型,和若干個byte的內容,內容根據類型來決定(boolean/byte為1個byte, char/short為2個byte,float/int為4個byte, double/long為8個byte,引用類型為identifierSize個byte)

     10. 2個byte的靜態變量個數,后面是每個靜態變量的,identifierSize個byte的變量名id, 1個byte的變量類型,和若干個byte的內容,內容根據類型來決定(見類對象基本信息的第9條)

      11.  2個byte的成員變量個數,后面是每個成員變量的,identifierSize個byte的變量名id,1個byte的變量類型

2、說明:

(1)類里面的常量很多地方都沒有用上,所以常量個數一般為0

(2)類的靜態變量的名稱類型及值是放在類對象里面的,成員變量的名稱和類型也是放在類對象里面的,但是實例的值是放在實例對象里面的

實例對象

1、基本信息:

  1. identifierSize個byte的實例對象id
  2. 4個byte的棧序列號
  3. identifierSize個byte的類id
  4. 4個byte的占用字節數
  5. 實例的變量的值

2、說明:

  1. 實例的值為實例對象的成員變量值,順序為當前類的變量值,順序為類對象基本信息中第11條中的順序,然后是父類的變量值
  2. 變量的值基本類型都有默認值,引用類型默認值為0,占用字節數(見類對象基本信息的第9條)

基本類型數組

1、基本信息:

  1. identifierSize個byte的數組對象id
  2. 4個byte的棧序列號
  3. 4個byte的數組長度
  4. 1個byte的元素類型
  5. 元素的值列表

2、說明:

  1. 元素的值(見類對象基本信息的第9條)

對象數組

1、基本信息:

  1. identifierSize個byte的數組對象id
  2. 4個byte的棧序列號
  3. 4個byte的數組長度
  4. identifierSize個byte的元素類id
  5. 元素的值列表

內存分配

當一個線程啟動的時候,進程會去系統內存生成一個線程棧

每當發生一次方法調用,就會向棧中壓入一個棧楨,當方法調用完之后,棧楨會退出

在運行過程中,如果有對象的new操作的時候,進程會去堆區申請一塊內存

關于運行時內存的詳細情況,可以查找相關的資料

內存回收規則

如果一個對象不能騎過gc root引用可達,那么這個對象就可能要被回收

對象回收規則包括

  1. 實例屬性被實例引用,只有當實例被回收了實例屬性才能被回收(只針對強引用)
  2. 類對象被實例引用,只有當一個類的所有實例都被回收了,類才能被回收
  3. 類對象的父類,classLoader對象,signer對象, protection domain對象被類引用,只有當類被回收了,這些才能被回收
  4. 局部變量(線程棧中)的作用域為一個大括號 
  1. public void test(){  
  2. Object a = new Object();//obj 1  
  3. Object b = new Object();//obj 2  
  4.  
  5. Object c = new Object();//obj 3  
  6. a = null;//obj 1可以被回收了  
  7. }//obj 3可以回收了  
  8. }//obj 2可以被回收了 

 

分析工具簡介

分析dump文件,我們可以用jdk里面提供的jhat工具,執行 

  1. jhat xxx.dump 

jhat加載解析xxx.dump文件,并開啟一個簡易的web服務,默認端口為7000,可以通過瀏覽器查看內存中的一些統計信息

一般使用方法

1、瀏覽器打開http:/127.0.0.1:7000

會列出一些功能,包括package下面各個類的概覽,及各個功能導航

2、點擊頁面的堆內存統計

有一個表格,對象類型,實例個數,實例所占用內存大小,哪種類型的對象占用了內存最多一目了然

3、點擊其中認為內存消耗太多的類名查看類詳情

主要展現該類下面各個實例的大小,以及一些鏈接導航

4、點擊references summary by type

如果某種類型的對象太多,那么有可能是引用它的那個類的對象太多

基本上一些簡單頁面的查詢,結合原代碼,就可以初步定位內存泄漏的地方

綜上,dump文件結構還是比較簡單的,這對于分析線程的執行情況非常有用,也是每一個Java程序員必須掌握的高級技能之一,你學會了嗎? 

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2023-11-19 23:29:22

Heap DumpJava

2017-09-26 16:32:03

JavaGC分析

2020-10-19 09:09:46

Class文件加載過程

2020-11-17 09:55:48

Java

2016-12-28 19:50:33

大數據數據采集大數據平臺

2017-09-20 08:48:09

JVM內存結構

2016-11-09 15:23:44

2018-09-03 13:14:41

小程序APP微信

2017-11-01 15:38:54

jvm知識點總覽

2017-10-17 14:02:30

jvm調優工具

2017-09-22 15:15:23

jvm調優命令

2018-02-06 09:25:35

數據分析分析方法分析工具

2021-10-11 19:54:04

JVM面試虛擬機

2019-10-24 10:28:06

2017-02-07 16:16:02

2012-01-11 11:28:00

JavaJVM

2024-06-04 12:32:42

.NET開發內存泄漏

2017-07-06 13:18:37

深度學習應用問題及趨勢

2021-11-21 23:03:38

jvm調優虛擬機

2020-07-21 14:19:18

JVM編程語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 最新日韩在线 | 成人黄色电影在线播放 | 亚洲福利av| 亚洲精品一| 黄色激情毛片 | 精品免费国产视频 | 国产在线一区二区 | av国产在线观看 | 日韩欧美久久 | 天天久| 特级一级黄色片 | 国产高清免费视频 | 欧美一级大片 | 亚洲 中文 欧美 日韩 在线观看 | 91国内在线观看 | 日本免费在线观看视频 | 亚洲人在线播放 | 国产精品国产精品国产专区不卡 | 中文字幕av一区二区三区 | 国产激情一区二区三区 | 亚洲综合在线播放 | 亚洲国产中文字幕 | 欧美一级免费 | 色本道| 在线观看三级av | 精品视频一区二区 | 懂色一区二区三区免费观看 | 91豆花视频 | 日韩色图视频 | 日本在线一区二区 | 最新一级毛片 | 一区二区三区中文字幕 | 国产成人精品综合 | 欧美精品一区二区三区四区五区 | gogo肉体亚洲高清在线视 | 欧美一区二区三区在线观看视频 | 亚洲第一视频网站 | 国产精品亚洲一区二区三区在线 | 国产一区二区三区在线 | 亚洲成人免费在线观看 | 亚洲高清免费 |