JVM運行時數據區
概述:本文爲JVM系列教程的第一課,主要陳述Java運行時數據區模型,及各個部分的作用。
附加知識點
- intern()方法講解
- String,Integer,int的==問題
在我第一次實習面試騰訊時,面試官問的問題就有JVM,在那時,我想學這個有什麼用,後面我一步步瞭解了JVM,仍然感覺這東西很虛,但是,現在,我想我們需要改變態度,因爲JVM真的有很多的使用價值,比如線上排查問題等等
JVM
內存數據區域:線程共享區+線程獨享區
線程共享:java堆+方法區
線程獨享:java虛擬機棧+程序計數器+本地方法棧
線程共享區會發生多線程併發的問題,注意,這並不是本文的重點,不過讀者可訪問我的多線程併發的文章
1.程序計數器
程序計數器
是什麼:是程序運行的指針,用於標誌和引導java代碼的執行順序,以及線程上下文切換後正確恢復至上次運行狀態
爲什麼:爲了線程能夠正確恢復,所以需要
特點:唯一一個不會發生OOM(OutOfMemoryError的一塊區域)
2.Java虛擬機棧
是什麼:java方法執行的內存模型,用於存放局部變量表,操作數棧,動態鏈接,方法返回類型
那什麼是局部變量表,局部變量表包括八種基本數據類型+reference(存放的對象引用,可能是直接引用,也有可能存放的是對象的句柄)
操作數棧:方法進行的運算,用操作數棧來保留結果
動態鏈接:不瞭解,也不重要
方法返回類型:很容易理解
注意:當虛擬機棧的棧幀數量超過虛擬機的規定時,會發生StackOverFlowError錯誤。
3.本地方法棧
與Java虛擬機棧相同,只不過它是爲本地方法提供服務
存儲的類型均一樣,也會發生StackOverFlowError錯誤
注意:HotSpot將本地方法棧+虛擬機棧合二爲一
4.方法區
注意:不要因文生意
是什麼:方法區並不是Java方法執行的內存模型,java虛擬機棧纔是,方法區是存放類信息,常量,靜態變量和編譯後的代碼的一塊區域
需要注意的是它有常量池。這樣會引發String == 問題,後文轉述此問題
5.Java堆
用於存放具體的對象,以及數組
又分爲兩個區:新生代,老年代
是垃圾回收的主要區域,我將此用了一片完整的博客專門陳述,包括垃圾回收算法,垃圾回收器,minorGC ,FullGC等等。
6.堆外內存
直接內存:受本機內存的影響,也會發生OOM,當heap利用率很低但發生OOM時需要考慮這個問題
好了,現在我們開始講述 String == int,Integer == 問題吧
public class FinalDemo {
public static void main(String[] args) {
String a = "abc";//分配在常量池中
String b = "abc";//分配在常量池中
String c = "a"+"bc";////分配在常量池中
String e = "a";//分配在常量池中
String d = e+"bc";//分配在堆中,只要有變量就在堆中
String str = new String("abc");//分配在堆中
System.out.println("begin");
System.out.println(a==b);//true
System.out.println(a==str);//false
System.out.println(str.intern()==a);//true,因爲intern()會檢查常量池中是否存在,
//不存在則往常量池中存儲一個,然後返回此引用。
System.out.println(a==d);//false
System.out.println(a==c);//true
}
}
注意:原則1.只要分配在堆中,就一定不相等,但是在常量池中就一定相等
原則2.String d = e+"bc";//存在變量,分配在堆中
String str = new String("abc");//new分配在堆中
intern():比較的是常量池引用
System.out.println(str.intern()==a);//true,因爲intern()會檢查常量池中是否存在,
//不存在則往常量池中存儲一個,然後返回此引用。
上面是String的==,現在說說Integer的==方法,
public class FinalDemo {
public static void main(String[] args) {
Integer num1 = 10;
int int1 = 10;
Integer num2 = 10;
Integer integer2 = new Integer(10);
System.out.println(num1 == num2);//true,因爲存在緩衝區
System.out.println(num1 == int1);//自動拆裝,true
System.out.println(integer2 == num2);//一個在緩存區,一個在堆,所以false
Integer integer3 = 128;
Integer integer4 = 128;
System.out.println(integer3 == integer4);//false,緩存區只會緩存-128到127的
}
}
下一篇:對象的產生及垃圾回收算法