記憶體結構篇:堆
阿新 • • 發佈:2020-11-15
一、定義
Java 堆(Heap)(執行緒共享)
- 所有執行緒共享的一塊記憶體區域,在虛擬機器啟動時建立。
- 此記憶體區域的唯一目的就是存放物件例項,“幾乎”所有的物件例項都在這裡分配記憶體(用new建立的類變數才是例項)
特點:
- 它是執行緒共享的,堆中物件都需要考慮執行緒安全的問題
- 有垃圾回收機制,是垃圾回收的主要區域(“GC堆”)(Garbage Collected Heap)
- 現代的垃圾收集器基本都是採用分代收集演算法,其主要的思想是針對不同型別的物件採用不同的垃圾回收演算法。可以將堆分成兩塊:
- 新生代(Young Generation)
- 老年代(Old Generation)
- 堆不需要連續記憶體,並且可以動態增加其記憶體,增加失敗會丟擲 OutOfMemoryError 異常(但對於大物件如陣列物件,多數虛擬機器實現出於實現簡單、儲存高效的考慮,很可能會要求連續的記憶體空間)
可以通過 -Xms 和 -Xmx 這兩個虛擬機器引數來指定一個程式的堆記憶體大小,第一個引數設定初始值,第二個引數設定最大值
java -Xms1M -Xmx2M HackTheJava
二、堆記憶體溢位
物件例項一直被使用,同時一直增加對堆記憶體的佔用,導致堆記憶體無法釋放,出現 OutOfMemoryError 異常
/** * 演示堆記憶體溢位 java.lang.OutOfMemoryError: Java heap space * -Xmx8m */ public class Demo1_5 { public static void main(String[] args) { int i = 0; try { List<String> list = new ArrayList<>(); String a = "hello"; while (true) { list.add(a); // hello, hellohello, hellohellohellohello ... a = a + a; // hellohellohellohello i++; } } catch (Throwable e) { e.printStackTrace(); System.out.println(i); } } }
報錯資訊:
24 java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3332) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448) at java.lang.StringBuilder.append(StringBuilder.java:136) at cn.itcast.jvm.t1.heap.Demo1_5.main(Demo1_5.java:19)
三、堆記憶體診斷
- jps 工具
- 檢視當前系統中有哪些 java 程序
- jmap 工具
- 檢視堆記憶體佔用情況 jmap - heap 程序id
- jconsole 工具
- 圖形介面的,多功能的監測工具,可以連續監測
- jvisualvm 工具
- 圖形介面,和 jconsole 類似,可以使用堆 Dump ,檢視物件個數等資訊
案例:
- 垃圾回收後,記憶體佔用仍然很高
/**
* 演示檢視物件個數 堆轉儲 dump
*/
public class Demo1_13 {
public static void main(String[] args) throws InterruptedException {
List<Student> students = new ArrayList<>();
for (int i = 0; i < 200; i++) {
students.add(new Student());
// Student student = new Student();
}
Thread.sleep(1000000000L);
}
}
class Student {
private byte[] big = new byte[1024*1024];
}