由於java時運行在虛擬機上的,因此與C、C++等語言不同,java可以自己進行內存垃圾的回收,不需要程序員自己處理對象的銷燬。
但是掌握GC對於我們對jvm調優有很大的幫助。
對於jvm的內存模型我們可以看到:
按照線程共享的方式可以分爲:
- 線程共享:堆,方法區
- 非線程共享:程序計數器,JVM棧,本地方法棧
解釋下各部分的含義:
- 方法區:主要存儲JVM加載的類信息,靜態變量,常量,即時編譯器編譯的代碼(這裏涉及到即時編譯器JIT相關內容,以後再做介紹)
- 堆:主要存儲生成的對象信息,即對象的實例。
- 程序計數器:程序執行的順序,當前執行的字節碼的行號。當java文件被編譯成class以後會形成一組以8位字節爲基礎單位的二進制流。程序運行到哪一步就是根據改變計數器 來實現的。最明顯的使用就是,當採用多線程的時候,單一處理器只能在一個時間點運行一個線程,而當多個線程搶佔資源或者共享資源的時候,需要記錄每個線程的程序執行到什麼位置,因此程序計數器是線程級的,各線程之間的計數器互不影響。
- JVM棧:主要存儲局部變量,操作數棧,動態鏈接,方法出口信息等。其中比較重要的就是局部變量表這塊,其中不光包括一些基本的數據類型,如int,long等 還包括一些對象的引用,如Integer等對象的地址。
- 本地方法棧:爲虛擬機使用到的native方法,使用native修飾的java方法只有聲明,他的實現需要用到其他語言。native關鍵字說明其修飾的方法是一個原生態方法,方法對應的實現不是在當前文件,而是在用其他語言(如C和C++)實現的文件中
比如現在有一個類
package dto;
import java.io.Serializable;
public class StudentDto implements Serializable {
/**
*
*/
private static final long serialVersionUID = 3676795379790467770L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
當通過StudentDto studentDto = newStudentDto();創建對象的時候,內存會爲做如下的操作
JVM棧中主要存儲的是對象的引用,堆中存放的是對象的數據。因此在內存回收的時候,主要針對的是堆內存的回收。
根據分代原理將內存劃分爲年輕代,年老代和持久代,其中持久代主要存儲的是編譯的類,方法,常量池,字段和方法數據,構造函數和普通方法的字節碼內容以及類、實例、接口初始化時需要使用到的特殊方法等數據。
具體分代如下圖
根據複製算法:
其中一個Eden區,兩個 Survivor區(from區、to區)。大部分對象在Eden區中生成。當Eden區滿時,還存活的對象將被複制到from區,當這個區滿時,執行normal gc,此區的存活對象將被複制到to區,當這個區也滿了的時候,執行full gc,從第一個from區複製過來的並且此時還存活的對象,將被複制到“年老區"。
那麼我們如何判斷對象是否需要被移除內存呢?
目前有兩種算法,一種是引用計數器算法,還有一種是可達性分析算法
先來說說引用計數器算法:當對象被引用的時候會在對象計數器上+1,當引用失效的時候計數器-1。但是隨之而來就出現了問題,如果兩個對象互相引用,雖然兩個對象都爲null,但是不會被收回。
class TestA{
public TestB b;
}
class TestB{
public TestA a;
}
public class Main{
public static void main(String[] args){
A a = new A();
B b = new B();
a.b=b;
b.a=a;
a = null;
b = null;
}
}
因此現在的java垃圾回收算法多用可達性分析算法。這裏引用一張書上的圖片
object1是“GC ROOT”的對象作爲起始點,因此object2,object3,object4都是可達的。而5,6,7是不可達的,因爲從object1向下搜索形成的引用鏈不可達。因此5,6,7會被判斷爲可回收的對象。而可作爲GC ROOT的可以是:
1.虛擬機棧(棧幀中的本地變量表)中引用的對象。
2.方法區中類靜態屬性引用的對象。
3.方法區中常量引用的對象。
4.本地方法棧中JNI引用的對象。