深入java week1-01 字節碼、內存、GC、調試工具

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1. java字節碼技術"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1.1 什麼是字節碼?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 字節碼(Java bytecode),是由Java編譯器把Java代碼轉換後,可以由java虛擬機無腦執行的指令集。也是java跨平臺的核心所在。Java維護者(組織)爲所有主流操作系統提供了一個Java虛擬機,這些虛擬機向上可以識別java字節碼,向下則適配本地環境,執行字節碼裏面的指令,在轉換成cpu執行指令。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"它是程序的一種低級表示,可以運行於Java虛擬機上。將程序抽象成字節碼可以保證Java程序在各種設備上的運行。計算機裏面的很多事情問題都可以通過增加一箇中間層來解決,很顯然,字節碼+JVM就是這麼一箇中間層,解決跨平臺的問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Java bytecode由單字節(byte)的指令組成,理論上最左支持256個操作碼(opcode)。實際上Java只是用了200個左右的操作碼,還有一些操作碼則保留給調試操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根據指令的性質,主要分爲四個大類:"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"棧操作指令,包括與局部變量交互的指令"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Java虛擬機(JVM)是一個基於棧的計算機。所有的計算都發生在棧上。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"程序流程控制指令"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"程序的流程控制指令,比如,for,if,函數調用"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"對象操作指令,包括方法調用指令"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"java是一個面向對象的語言,創建一個對象,調用對象的方法。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"算數運算以及類型轉換指令。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1.2 查看字節碼"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"代碼"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5d/5db039487bf6d60a9ae32ba7f6e7c631.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":2,"normalizeStart":2},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"查看字節碼"}]}]}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"javac xxx.java 生成class文件"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"javap -c xxx.class 查看字節碼"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3a/3a28f4bd6b0b2dfab606cfef7b7dacba.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 實際上,class文件裏面保存的都是字節碼,0到255的數字,上圖展示的是助記符,方便記憶和閱讀用的。aload_0,return等都有自己對應的操作碼的。"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"javap -c -verbose xxx.class 查看更信息的字節碼信息"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/44/442c79ce6a3d2649eddabc6cee22edcf.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 上圖中,有jdk的版本號,類的屬性(public),還有常量表。代碼行號表(調試的時候可以看到指令對於的行號)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":3,"normalizeStart":3},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"執行流程"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/84/84388761bff510aa80b51c655886aed8.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b9/b9baf307ebf56822895b5732eba02d32.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":" 執行的時候,從常量表中獲取到常量值,在放到程序棧(變量表)中盡心計算。"}]},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2. 類加載"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.1 類的生命週期"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"加載(Loading):找class文件,並讀入程序內存中"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"通過類名com.xxx.Class從各種classpath目錄裏面找到對應類,也可以自定義類加載器,從網絡上加載類或jar包。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"驗證(Verification): 驗證格式,依賴"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"驗證格式是否正確。版本號。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"類之間的相互引用關係。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"準備(Preparation): 靜態字段,方法表"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"抽取類裏面的靜態字段"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"抽取類裏面的方法。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"搭建類的結構(骨架)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"解析(Resolution): 符號解析爲引用"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"把各種符號替換成引用。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"初始化(Initialization): 構造器,靜態變量賦值,靜態代碼"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"靜態變量賦值"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"靜態代碼執行"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"然後這個類就可以創建實例了。可以被使用了。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"使用(Using): 創建類實例,並使用"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"卸載(Unloading): 清除類的信息"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.2 什麼時候會加載類,會初始化類"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"當虛擬機啓動時,初始化用戶指定的主類。(main方法所在的類)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"當遇到用以新建目標類實例的new指令時,初始化new指令的目標類,就是new一個類的時候要初始化。(創建類的實例,那肯定需要類被加載了。)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"當遇到調用靜態方法的指令時,初始化該靜態方法所在的類。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"當遇到訪問靜態字段的指令時,初始化該靜態字段所在的類。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"子類的初始化會觸發父類的初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"如果一個接口定義了default方法,那麼直接實現或間接實現該接口的類的初始化,會觸發該接口的初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"使用反射API對某個類進行反射調用時,初始化這個類,反射調用要麼是已經有實例了,要麼是靜態方法,都需要初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"當初次調用MethodHandle實例時,初始化該MethodHandle指向的方法所在的類。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":9,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.3 什麼時候會加載類,不會初始化類"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"通過子類引用父類的靜態字段,只會觸發父類的初始化,而不會觸發子類的初始化。但子類肯定是被加載了的。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"定義對象數組,不會觸發類的初始化。數組只是一個聲明,實際上還沒有創建對象呢。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"常量在編譯期間會存入調用類的常量池中,本質上並沒有直接一用定義常量的類,不會觸發定義常量所在的類。比如:java字符串字面量\"xxxx\"其實就是一個String常量了。但是並不會觸發String類的初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"通過類名獲取Class對象,不會觸發類的初始化。Hello.Class不會讓Hello類初始化。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"通過Class.forName加載指定類時,如果指定參數initialize爲false時,不會觸發類初始化,其實這個參數是告訴虛擬機,是否需要對類進行初始化。Class.forName(\"jvm.Hello\")默認會初始化Hello類。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"通過ClassLoader默認的loadClass方法,不會觸發初始化動作(類加載了,但是不初始化)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"size","attrs":{"size":14}},{"type":"strong"}],"text":"所謂加載類,不初始化類指的就是,會從class文件裏面加載類的字節碼,但是並不會執行靜態字段的賦值,靜態代碼塊的執行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.4 類加載器"}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"啓動類加載器(BootstrapClassLoader)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"加載JVM啓動的核心繫統類"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"擴展類加載器(ExtClassLoader)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"擴展的類,也是在jdk裏面自帶的。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"應用類加載器(AppClassLoader)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"加載程序員寫的代碼,jar包。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"怎麼保證類不會重複加載?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"雙親委託:應用類加載器在加載類的時候,會先去擴展類加載器裏面找類是否已被加載,如果沒有就去啓動類加載器找,如果還沒有,則自己加載類。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"負責依賴:加載一個類的時候,還需要把這個類依賴的其它類也給加載進來。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"緩存加載:類被加載完後,會緩存起來。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"自定義類加載器"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"自定義類加載器加載出來的類是不一樣的,哪怕都是從同一個class文件加載進來的類,但是實例是不能相互類型轉換的。因爲沒有共同的上一級加載器。java中類其實也是一個對象,不同的加載器加載的類,就相當於2個類對象,雖然對象的內容是一樣的,但是地址什麼的就不一樣了(比喻)。基於這個特性,可以加載不同版本的類,解決類兼容的問題,比如引入了一個外部工具,這個工具依賴了xxx.class 1.0.0。但是現有的代碼也依賴的卻是xxx.class 1.1.0這樣就勢必要加載2個版本的xxx.class了。那麼自定義類加載器就派上用場了。"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4b/4bb7ed7c21fbe37e56364572ed149e0e.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.5 添加引用類的幾種方式(就是發現類)"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"把類/jar放到JDK的lib/ext下,或者-Djava.ext.dirs指定類查找路徑"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"java-cp/classpath或者class文件放到當前路徑"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自定義ClassLoader加載。這個就比較靈活了,可以從網絡上下載一個類。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"拿到當前執行類的ClassLoader,反射調用addUrl方法添加jar或者路徑。說白了,還是添加路徑其他的類加載器才能找到類、jar包。(JDK9就不能用這種方法了,提供了新方法。)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"3. JVM內存模型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"4. JDK內置的命令行工具"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4.1 工具功能展示"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.1 jps/jinfo"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"查看當前系統啓動的java進程。就跟linux的ps命令一樣,只是jps只顯示java進程"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jps -mlv :查看更詳細的信息。jvm的啓動參數,垃圾回收算法等。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null}}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.2 jstat"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jstat -gc 98800 1000 20 查看進程98800的內存,和gc情況,1000表示每秒刷新一次,顯示20次。s0c存活區0的容量,s0u表示存活區0使用的內存數。EC表示伊甸區的容量。OC老年區的容量。MC表示元數據區的容量。YGC表示youngGC次數。YGCT表示youngGC的總時間。FGC全量垃圾回收的冊數,FGCT表示全量GC的總時間。單位都是字節。"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/67/675b5e7016b9c15d51f1d715f1bd7842.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"jstat -gcutil 98800 1000 20: 查看各個區域內存的使用率。百分比"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.3 jmap 查看更詳細的jvm信息,jvm裏面的所有對象,以及對象個數,使用的字節數。如果某個對象特別多。可能就是內存泄漏了。"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"jmap -histo pid"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/7d/7da5842e69d18f5cd3bfb59966b47897.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"jmap -heap 14068 查看堆內存信息"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d8/d86eb8ac036c5d9da87e7669aa6b5a5e.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.4 jstack"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jstack pid:查看jvm所有線程的棧。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.5 jcmd"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jcmd是一個比較綜合的命令行工具。和上面的那些都是職責單一的。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jcmd 14068 help :查看指定進程,支持哪些工具。"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/50/50e16c9283be36dc0b19dcd94d0ef3c3.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"jcmd pid Thread.print: 查看jvm的所有線程棧。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4.1.6 jrunscript/jjs"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"執行js腳本命令。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"5. JDK內置圖形化工具"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"說明:功能其實和命令行工具差不多,只是有窗口界面,比較方便。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.1 jconsole"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 圖形化顯示JVM內存,線程,cpu的使用情況。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/57/5793de87945aa9c44a42fc725a0bc053.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.2 jvisualvm"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 抽樣統計功能,比jconsole更好用一點。更強大一點。可以查看一段時間(單位時間)系統的狀態。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/66/66a0794b85ab7c950ce37c171ac0cd24.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.3 jmc"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"死鎖都能檢測出來。"}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章