柚子快報激活碼778899分享:java JVM入門
柚子快報激活碼778899分享:java JVM入門
文章目錄
什么是程序計數(shù)器介紹下Java堆內(nèi)存結(jié)構(gòu)在Java7與8的區(qū)別什么是虛擬機(jī)棧垃圾回收是否涉及棧內(nèi)存棧內(nèi)存分配越大越好嗎方法內(nèi)的局部變量是否是線程安全的
什么情況下棧內(nèi)存溢出堆棧的區(qū)別是什么解釋下方法區(qū)介紹下運行時常量池
什么是類加載器類加載器有那些什么是雙親委派模型、JVM為什么采用雙親委派
類裝載的執(zhí)行過程對象什么時候可以被垃圾器回收那些對象可以作為GC Root
垃圾回收算法有那些JVM的分代回收MinorGc、MixedGc、FullGc區(qū)別JVM垃圾回收器有那些概述G1垃圾回收器強(qiáng)軟弱虛JVM調(diào)優(yōu)參數(shù)可以在哪里設(shè)置參數(shù)值JVM調(diào)優(yōu)參數(shù)有那些JVM調(diào)優(yōu)的工具Java內(nèi)存泄漏如何排查CPU飆高排查方案OOM排查 (說這個?。?/p>
什么是程序計數(shù)器
程序私有的,內(nèi)部保存的字節(jié)碼的行號,用于記錄正在執(zhí)行的字節(jié)碼指令的地址。
介紹下Java堆
java堆就是線程共享的區(qū)域,主要用來保存對象實例、數(shù)組等,當(dāng)堆中沒有內(nèi)存空間可分配也無法擴(kuò)展的時候就會拋出OOM異常 組成:年輕代+老年代 年輕代被劃分為三部分,Eden區(qū)和兩個相同的Survior區(qū)(幸存者區(qū)) 老年代主要保存生命周期長的對象
內(nèi)存結(jié)構(gòu)在Java7與8的區(qū)別
在java8之后將原有堆中的方法區(qū)/永久代(主要保存了類信息、常量、編譯后的代碼) 放在了本地內(nèi)存的元空間中,原因是避免OOM,放在內(nèi)存溢出
什么是虛擬機(jī)棧
每個線程運行時所需要的內(nèi)存,被稱為虛擬機(jī)棧,特點是先進(jìn)后出 每個棧由多個棧幀組成,就是每次方法調(diào)用時所占用的內(nèi)存
垃圾回收是否涉及棧內(nèi)存
垃圾回收就是指堆內(nèi)存當(dāng)棧幀彈棧之后內(nèi)存就會釋放
棧內(nèi)存分配越大越好嗎
不是,默認(rèn)是1024k,棧幀過大會導(dǎo)致線程數(shù)變少,通常就是用默認(rèn)的
方法內(nèi)的局部變量是否是線程安全的
如果方法內(nèi)局部變量只作用于方法內(nèi),他是線程安全的但如果局部變量引用了對象,并逃離了方法的作用范圍,此時需要考慮線程安全
什么情況下棧內(nèi)存溢出
棧幀過多導(dǎo)致棧內(nèi)存溢出,典型問題:遞歸棧幀過大導(dǎo)致棧內(nèi)存溢出(一般不會出現(xiàn),也沒有遇到過)
堆棧的區(qū)別是什么
棧內(nèi)存一般用來存儲局部變量和方法調(diào)用的,堆內(nèi)存是用來存儲Java對象和數(shù)組的,堆會GC垃圾回收,棧不會棧內(nèi)存是線程私有的,堆內(nèi)存是線程共有的(需要考慮線程安全問題)兩者拋出異常錯誤也不同, 棧內(nèi)存不足是SOF、堆內(nèi)存不足是OOM
解釋下方法區(qū)
方法區(qū)Method Area 是各個線程共享的內(nèi)存區(qū)域,主要存儲類的信息、運行時常量池
介紹下運行時常量池
當(dāng)類被加載,它的常量池信息就會放入運行時常量池,并把里面的符號地址變?yōu)檎鎸嵉刂?常量池是可以看作是一張表,虛擬機(jī)指令根據(jù)這張常量表找到要執(zhí)行的類名、方法名等信息;
什么是類加載器
JVM只會運行二進(jìn)制文件,類加載器的作用就是將字節(jié)碼文件加載到JVM中從而讓Java程序能夠啟動
類加載器有那些
啟動類加載器、擴(kuò)展類加載器、應(yīng)用類加載器、自定義類加載器
什么是雙親委派模型、JVM為什么采用雙親委派
雙親委派模型就是加載某一個類時,先委托上一級的加載器進(jìn)行加載,如果上級加載器也有上級,就會繼續(xù)向上委托,如果該類委托上級沒有被加載,子類加載器就會嘗試加載該類 至于JVM為什么采用雙親委派是因為避免某個類被重復(fù)的加載,當(dāng)父類已經(jīng)加載后則無需重復(fù)加載,保證唯一性,也能夠保證類庫API不會被更改
類裝載的執(zhí)行過程
加載-驗證-準(zhǔn)備-解析=初始化-使用-卸載
對象什么時候可以被垃圾器回收
如果一個或多個對象沒有任何的引用指向它,那么這個對象就會被定位為垃圾,就可能被垃圾回收器回收 定位垃圾的方式有兩種:
引用計數(shù)法(當(dāng)對象出現(xiàn)循環(huán)引用時,會出現(xiàn)內(nèi)存泄漏風(fēng)險)可達(dá)性分析算法(現(xiàn)在虛擬機(jī)都采用的此方法) 掃描堆中的對象,看是否能夠沿著GC Root對象為起點的引用鏈找到該對象,如果不能找到就表示可以被回收
那些對象可以作為GC Root
虛擬機(jī)棧(棧幀中的本地變量表)中引用的對象方法區(qū)中類靜態(tài)屬性引用的對象方法區(qū)中常量引用的對象本地方法棧中JNI引用的對象 都指向堆中的一塊區(qū)域
垃圾回收算法有那些
標(biāo)記清除算法: 分為2個階段:標(biāo)記和清除 根據(jù)可達(dá)性分析算法得出得垃圾進(jìn)行標(biāo)記 對這些標(biāo)記可回收的內(nèi)容進(jìn)行垃圾回收 標(biāo)記和清除速度塊,但碎片化嚴(yán)重,內(nèi)存不連貫標(biāo)記整理算法 與標(biāo)記清除算法差不,將存活對象都向內(nèi)存另一端移動,然后清理邊界以外的垃圾,無碎片,但對象需要移動,效率較低復(fù)制算法 在垃圾對象多的情況下,效率比較高,并且清理后內(nèi)存無碎片化的,但是它需要分配2塊內(nèi)存空間,在同一時刻,只能使用一半,內(nèi)存使用率低
JVM的分代回收
首先將新創(chuàng)建的對象,都會分配到eden區(qū) 之后當(dāng)eden區(qū)內(nèi)存不足時,標(biāo)記eden與from的存活對象,將存活的對象采用復(fù)制算法復(fù)制到to中,復(fù)制完畢清除eden和from內(nèi)存 經(jīng)過一段時間后eden的內(nèi)存又出現(xiàn)不足,就會標(biāo)記eden和to區(qū)域存活的對象,并復(fù)制到from區(qū) 當(dāng)幸存區(qū)對象被來回的回收多次之后,就會晉升到老年代(辛存區(qū)內(nèi)存不足或大對象會提取晉升)
堆的區(qū)域劃分
堆被劃分為兩份:新生代和老年代【1:2】對于新生代,內(nèi)部又被劃分為三個區(qū)域:eden伊甸園區(qū)和survivor幸存者區(qū)(分為from和to)【8:1:1】
MinorGc、MixedGc、FullGc區(qū)別
MinorGc:young Gc 發(fā)生在新生代的垃圾回收,暫停時間短(STW) MixedGc:新生代+老年代部分區(qū)域的垃圾回收,G1收集器特有 FullGc:新生代+老年代完整垃圾回收,暫停時間長(STW),盡量避免
JVM垃圾回收器有那些
串行垃圾收集器:SerialGC、Serial Old GC并行垃圾收集器:Paraller Old GC、ParNew GCCMS(并發(fā))垃圾收集器:CMS GC作用在老年代G1垃圾收集器:作用在新生代和老年代
概述G1垃圾回收器
G1垃圾回收器應(yīng)用在新生代和老年代中,在JDK9之后垃圾回收器默認(rèn)使用G1, G1垃圾回收器劃分了多個區(qū)域,每個區(qū)域都可充當(dāng)eden、survivor、old、humongous,其中humongous存儲大對象的 G1垃圾回收器分為三個階段: 1.新生代回收STW 2.并發(fā)標(biāo)記,就是重新標(biāo)記STW 3.混合收集 采用復(fù)制算法,如果并發(fā)失敗,會觸發(fā)full GC
強(qiáng)軟弱虛
強(qiáng)引用: 只要能被GC Root找到就是強(qiáng)引用,平時new的也是強(qiáng)引用。強(qiáng)引用的對象,即使出現(xiàn)OOM也不會對該對象進(jìn)行回收,死都不收 軟引用: 需要用SoftReference類來實現(xiàn),軟引用在內(nèi)存夠用時就會保留,不夠用時就回收 弱引用: 需要用WeakReference類來實現(xiàn),只要垃圾回收機(jī)制運行,不管JVM內(nèi)存是否足夠,都會回收 虛引用: 必須配合引用隊列聯(lián)合使用,被引用的對象回收時,會被虛引用入隊,由Reference Handler線程調(diào)用虛引用相關(guān)方法釋放直接內(nèi)存
JVM調(diào)優(yōu)參數(shù)可以在哪里設(shè)置參數(shù)值
Xms 堆的初始化大小 Xmx最大大小
war包部署在tomcat中設(shè)置 修改TOMCAT_HOME/bin/catalina.sh文件(111行:JAVA_OPTS=“-Xms512m -Xmx1024m”) jar包部署在啟動參數(shù)設(shè)置 java -Xms512m -Xmx1024m -jar xxx.jar
JVM調(diào)優(yōu)參數(shù)有那些
設(shè)置堆空間的大小 -Xms堆初始化大小 -Xmx堆最大大小 默認(rèn)是物理內(nèi)存的1/4 為防止垃圾收集器在初始大小、最大大小之間收縮堆而產(chǎn)生額外的時間,通常設(shè)置成相同的值虛擬機(jī)棧的設(shè)置 每個線程默認(rèn)會開啟1M的內(nèi)存,用于存放棧幀、調(diào)用參數(shù)、局部變量等,工作中512k就夠用 -Xss 對每個Stack大小的調(diào)整年輕代中Eden區(qū)和兩個Survior區(qū)的大小比例 -XXSurvivorRation=8 #表示年輕代中分配比率:survivor:eden=2:8 默認(rèn)是8:1:1; 通過增大eden區(qū)的大小,來減少YGC發(fā)生的次數(shù),但在eden區(qū)滿的時候,由于占用的空間較大,導(dǎo)致釋放緩慢,STW時間較長的,所以一般是不確定的,需要根據(jù)程序情況調(diào)優(yōu)年輕代晉升老年代閾值 -XX:MaxTenuringThreshold=threshoid 默認(rèn):15 (取值范圍:0~15)設(shè)置垃圾回收收集器 默認(rèn)是并發(fā)的垃圾回收器 -XX:+UseParallelGC -XX:+UseParallelOldGC 設(shè)置垃圾回收期 -XX:+UseG1GC
JVM調(diào)優(yōu)的工具
命令常用的是:
jps 查詢進(jìn)程 jstack 查看java進(jìn)程內(nèi)線程的堆棧信息 jmap 查看堆轉(zhuǎn)信息 jmap -heap 進(jìn)程id jmap -dump:format=b,file=指定路徑/xxx.hprof 進(jìn)程id (生成堆轉(zhuǎn)信息dump文件) jhat 堆轉(zhuǎn)儲快照分析工具 jstat JVM統(tǒng)計監(jiān)測工具,用來顯示垃圾回收信息、類加載信息、新生代統(tǒng)計信息等
使用可視化工具查看:VisualVM
Java內(nèi)存泄漏如何排查
出現(xiàn)內(nèi)存泄漏的有三個地方
JVM stacks虛擬機(jī)棧 StackOverFlowError方法區(qū)/元空間 OOM:MetaspaceHeap 堆 OOM:java heap space
內(nèi)存泄漏和內(nèi)存溢出都涉及到Java虛擬機(jī)(JVM)中的內(nèi)存管理,但它們是不同的概念。 內(nèi)存泄漏(Memory Leak): 內(nèi)存泄漏是指程序中分配的內(nèi)存空間在不再需要時沒有被釋放,導(dǎo)致該內(nèi)存無法被重新使用,最終耗盡可用內(nèi)存。 典型的內(nèi)存泄漏場景包括對象被持續(xù)引用而無法被垃圾回收器回收、緩存對象無限增長、長時間存在的監(jiān)聽器未被移除等。 內(nèi)存溢出(Memory Overflow): 內(nèi)存溢出是指程序在申請內(nèi)存空間時,無法獲得足夠的內(nèi)存而導(dǎo)致無法繼續(xù)執(zhí)行。 典型的內(nèi)存溢出情況包括堆內(nèi)存溢出(Heap Overflow)和棧內(nèi)存溢出(Stack Overflow)。堆內(nèi)存溢出通常是由于創(chuàng)建了過多的對象而耗盡了堆內(nèi)存,而棧內(nèi)存溢出則是由于遞歸調(diào)用或者方法調(diào)用鏈過長而耗盡了棧內(nèi)存。
1.通過jmap指令獲取堆內(nèi)存快照dump 2.VisualVM分析dump文件 3.通過查看堆轉(zhuǎn)儲信息的情況,定位內(nèi)存溢出問題
CPU飆高排查方案
1.使用top命令查看占用CPU的情況,定位到那個進(jìn)程占用CPU較高 2.使用ps命令查看進(jìn)程中的線程信息 3.使用jstack命令查看進(jìn)程中那些線程出現(xiàn)問題了,最后定位原代碼
OOM排查 (說這個?。?/p>
工具:Jprofiler (老工具M(jìn)AT) 作用:分析Dump內(nèi)存文件,定位內(nèi)存泄漏;獲取堆的數(shù)據(jù);獲取大對象等 安裝:
1.安裝插件Plugins–>Jprofiler 2.官網(wǎng)下載Jprofiler軟件 無腦安裝(License key注冊碼需要獲取) 3.安裝完畢后–>Settings–>Tools–>Jprofiler 綁定軟件路徑(xxx\bin\jprofiler.exe)
測試代碼:
//在Configurations--Application--VM options設(shè)置參數(shù)
//-Xms 設(shè)置初始化內(nèi)存分配大小 默認(rèn) 1/64
//-Xmx 設(shè)置最大分配內(nèi)存 默認(rèn)1/4
//-XX:+PrintGCDetails 打印GC垃圾回收信息
//-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError OOM完整參數(shù)設(shè)置 Heap堆 Dump On條件 OutOfMemoryError既OOM錯誤 就Dump文件
public class Demo{
byte[] array = new byte[1*1024*1024];//1m
public static void main(String[] args){
ArrayList
int count = 0;
try{
while(true){
list.add(new Demo());
count = count + 1;
}
}catch(Error e){
System.out.println("count:"+count);
e.printStackTrace();
}
//獲取最大內(nèi)存
//long max = Runtime.getRuntime().maxMemory(); //字節(jié)
//獲取JVM的初始化總內(nèi)存
//long total = Runtime.getRuntime().totalMemory();
//轉(zhuǎn)MB --max/(DOUBLE)1024/1024
}
}
最后通過Jprofiler軟件分析Dump文件
柚子快報激活碼778899分享:java JVM入門
精彩內(nèi)容
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。