專題——JVM

JVM

下圖是JDK的結構圖(來源於網絡)
圖片來自網絡
不同版本JDK的JRE是不同的,JVM會將相同的字節碼文件解析成不同系統識別的0 1 二進制
在這裏插入圖片描述
JVM 的結構:

由以下代碼引入:

public class Demo {
	public static final double PI = 3.14;
	static Circle circle = new Circle();

	public static void main(String[] args) {
		Demo demo = new Demo();
		int c = demo.calculate();
		System.out.println(c);
	}

	public static int calculate() {
		int a = 2;
		int b = 3;
		int c = (a + b) * 2;
		return c;
	}
}

class Circle{
	private double radius;

	public Circle() {
		this(1.0);
	}
	public Circle(double radius){
        this.radius=radius;
    }
}

在這裏插入圖片描述
爲更加好理解棧幀,我們可以通過命令行查看Demo 的字節碼文件:

javap -c Demo.class > Demo.txt//-c 爲反彙編,可將字節碼文件編譯成更加容易理解的文件,並寫入到 Demo.txt文件中
Compiled from "Demo.java"
public class Demo {
  public static final double PI;

  static Circle circle;

  public Demo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class Demo
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: pop
      10: invokestatic  #4                  // Method calculate:()I
      13: istore_2
      14: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      17: iload_2
      18: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
      21: return

  public static int calculate();
    Code:
       0: iconst_2
       1: istore_0
       2: iconst_3
       3: istore_1
       4: iload_0
       5: iload_1
       6: iadd
       7: iconst_2
       8: imul
       9: istore_2
      10: iload_2
      11: ireturn

  static {};
    Code:
       0: new           #7                  // class Circle
       3: dup
       4: invokespecial #8                  // Method Circle."<init>":()V
       7: putstatic     #9                  // Field circle:LCircle;
      10: return
}

JVM指令手冊可以私聊我發給你們(免費)

堆的結構:
在這裏插入圖片描述
說明:分代的原因在於提高對象分配內存和垃圾回收的效率,新的對象會放在伊甸園區,當伊甸園區滿了之後會由執行引擎進行垃圾回收,即young GC或稱minor GC,存活的對象放入S1中,當伊甸園區再次滿的時候會再次進行minor GC,這次收集的是伊甸園區和S1中的垃圾,將兩個區中都存活的對象再放入S2中,而原先在S1中的對象的分代年齡+1,當伊甸園區再次滿的時候再將伊甸園區和S2中存活的對象放入S1中,原先在S2中的對象的分代年齡+1;當一個對象的分代年齡到達15的時候,會被放入老年代,當老年代放滿的時候會執行full GC,系統消耗非常高,應儘量避免full GC,一天、一週、一個月進行一次爲正常,還有很多規則使對象直接進入老年代,例如其中之一:當Eden中存活的對象大小大於S1的50%時,就直接進入老年代。

JVM調優基礎
當輸入java -version時
在這裏插入圖片描述
會出現client或者server兩種不同的機制,client機制更多的基於桌面級應用,分配的空間相對比server 少,但是server機制會造成空間浪費,這兩種機制可以在jre中修改。

可以進行JVM調優的點:

  1. 選擇client還是server機制
  2. 對堆的大小的分配,手動調參數
    例如:-Xms:初始化堆的大小
    -Xmx:最大堆大小
    -XX:New Size:n:設置年輕代的大小
  3. 垃圾收集器的選擇

JVM中的垃圾收集器:

在這裏插入圖片描述
連線表示收集器可以配合使用

serial收集器:唯一一個次收集器,是一個串行收集器,STW(stop the world):收集時暫停整個線程。(圖片來自網絡)

注意
新生代使用的是複製算法,而老年代使用的是標記-整理算法
在這裏插入圖片描述
parNew收集器:並行收集器,是CMS默認配合的收集器,多核CPU可以顯示出能力,單核和serial效果一樣。(圖片來自網絡)
在這裏插入圖片描述
parallel :提高吞吐率
系統吞吐率=代碼執行時間/(代碼執行時間+垃圾收集時間)

CMS收集器:垃圾收集和用戶線程併發執行

G1:新生代和老年代的垃圾都可以回收

常用的垃圾回收算法

1.引用計數:

一個對象有一個引用就加1,少一個引用就減1,如果爲0就回收,缺點是無法解決循環引用的問題

2.複製算法:

劃分爲兩個相等的區域,只複製正在處理的對象,複製過去可以有序的整理,沒有空間碎片,缺點:需要兩倍空間

3.標記-清除算法:

第一階段從引用的根節點開始標記所有被引用的對象,第二階段遍歷整個堆,將爲標記的對象清除。此算法需要暫停整個應用,同時,會產生內存碎片。

4.標記-整理算法:

此算法是對標記-清除的優化,使用標記-清除方法清除後,再將存活的對象壓入到堆中的一塊區域,按順序排好,解決了標記-清除的內存碎片問題和賦值的空間問題。

以上是自己對JVM所學整理的筆記,不完整,今後會逐步完善!

加油!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章