JVM
目錄
JVM
一、JVM概述
二、記憶體結構
三、堆中的 GC 回收程序
如何改變物件物件進入老年代的最大值?
四、GC如何判斷物件是否改被回收
五、垃圾收集的演算法
六、都有那些垃圾回收器
七、記憶體泄漏(不再使用的物件的記憶體不能被GC回收)
八、調優
九、JVM 思維導圖
一、JVM概述
JVM 是一種用于計算機設備的規范,它是一個虛構的計算機的軟體實作,簡單的說,JVM 是運行 byte code 位元組碼程式的一個容器,
它有一個解釋器組件,可以實作 JAVA 位元組碼和計算機作業系統之間的通信,java程式只需要在JVM 上一次編譯,多出運行,因此JAVA具有跨平臺性,
二、記憶體結構
- 方法區(常量池、靜態變數、建構式、類資料)
- 堆(物件、類實體、GC的主要區域)
- 新生區(Minor GC 、Full GC清理無用資料)
- 伊甸園(物件創建)
- 幸存 0 區
- 幸存 1 區
- 老年代(物件的宣告周期到老年代結束)(Full GC)
- 永久區(jdk 1.8 以后被元空間代替)(Major GC)
- 新生區(Minor GC 、Full GC清理無用資料)
- 程式計數器(記錄每個運行執行緒的記憶體地址)
- 虛擬機堆疊(每個方法創建都會創建一個堆疊,堆疊內的資料都是臨時的)
- 本地方法堆疊
- 直接記憶體
三、堆中的 GC 回收程序
物件會在 Eden(伊甸園)分配創建,當 Eden(伊甸園)沒有足夠空間時將發起一次 Minor GC(垃圾清理),當 Eden 執行 Minor GC 后還不足以為物件分配空間,則大的物件直接進入老年代,可以用引數設定大物件直接進入老年代,避免頻繁 Minor GC ,如果物件在 Eden 創建,發生 Minor GC 后仍然存活,且能被 Survivor 幸存去容納,年齡加 1, 達到一定年齡進入老年代,默認為 15,發生 Mrinor GC之前先檢查老年代最大可用連續空間是否大于新生代所有物件總空間,如果大于,說明 Minor GC 安全;否則會判斷是否被擔保失敗,如果擔保失敗了,判斷老年代最大連續空間是否大于歷次晉升到老年代物件的平均大小,如果大于則嘗試 Minor GC ,否則就執行 Full GC 進行物件回收,如果 Full GC 執行完畢后,物件仍然無法被創建,則直接拋出記憶體溢位的例外(java.lang.OutOfMemoryError),
如何改變物件物件進入老年代的最大值?
通過修改-XX:PretenureSizeThreshold引數來設定進入老年代的物件年齡,這樣也避免在 Eden(伊甸園)區和兩個 Survivor 之間發生大量的記憶體復制,(默認值為 15)
四、GC如何判斷物件是否改被回收

五、垃圾收集的演算法

六、都有那些垃圾回收器

七、記憶體泄漏(不再使用的物件的記憶體不能被GC回收)
記憶體泄漏的例子:
單例模式:
不正確使用單例模式是引起記憶體泄漏的一個常見問題,單例物件在初始化后將在JVM的整個生命周期中存在(以靜態變數的方式),如果單例物件持有外部的參考,那么這個物件將不能被JVM正常回收,導致記憶體泄漏,所以需要注意,盡量不要在單例中持有大物件,
各種連接:
比如資料庫連接、socket連接、檔案流等,除非其顯式的呼叫其close()方法將連接關閉,否則是不會自動被垃圾 回收的,
靜態集合類:
我們回圈申請Object物件,并將所申請的物件放入一個Vector中,如果我們僅僅釋放參考本身,那么Vector仍然參考該物件,所以這個物件對GC來說是不可回收的,
如果物件加入到Vector后,還必須從Vector中洗掉,最簡單的方法就是將Vector物件設定為null,
Static Vector v = new Vector(10);
for (int i = 0; i < 100; i++) {
Object o = new Object();
v.add(o);
o = null;
}
事件監聽器:
AWT的事件處理機制是一種委派式事件處理方式:普通組件(事件源)將整個事件處理委托給特定的物件(事件監聽器);當該事件源發生指定的事件時,就通知所委托的事件監聽器,由事件監聽器來處理這個事件,
比如常用的監聽器有ActionListener、KeyListener、MouseListener、MouseMotionListener(專門處理滑鼠運動事件的,比如滑鼠的移動和拖動)
如果在釋放物件的時候沒有記得洗掉這些監聽器,會增加記憶體泄露的機會,
import java.awt.*;
import java.awt.event.*;
public class TestButton {
public static void main(String args[])
{
Frame f = new Frame("Test");
Button b = new Button("Press Me!");
b.addActionListener(new ButtonHandler()); /*注冊事件監聽器*/
f.setLayout(new FlowLayout()); //設定布局管理器
f.add(b);
f.setSize(200,100);
f.setVisible(true);
}
}
//實作介面ActionListener才能做事件ActionEvent的處理者
class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e)
{
System.out.println("Action occurred");
}
}
八、調優

九、JVM 思維導圖

網址:
https://www.jianshu.com/p/99772ad092d3
https://zhuanlan.zhihu.com/p/34426768
https://blog.csdn.net/qq_41701956/article/details/81664921
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/233979.html
標籤:其他
上一篇:無限關機—C++黑客編程入門級專案 (完整原始碼 復制即可使用)
下一篇:詳解格式化字串漏洞利用(菜雞向)

