思考:java優勢巨大,爲什麼?
1.java一次編譯到處運行
2.java具有完整的內存管理機制,不需要每new一個對象,寫相應的內存回收代碼
JVM運行時數據區
1.程序計數器
是什麼?
程序計數器是一塊較小的內存空間,可以看做是當前線程字節碼的行號指示器
線程是一個獨立的執行單元,由cpu執行
字節碼解釋器通過改變這個計數器的值來選取下一條需要執行的字節碼指令,指令的循環,跳轉都需要依賴程序計數器
來完成
爲了線程切換後能回到正確的位置執行,每條線程都需要一個獨立的程序計數器,各線程之間的計數器互不影響,獨立存儲
,我們稱這類內存區域爲“線程私有”的內存
2.java虛擬機棧
作用於java方法的一塊內存區域
當棧長度超出指定長度是發生stackoverfloweError 棧溢出
eg:沒有終止條件的遞歸操作
public class A {
public static void a(){
int a = 111;
int b = 222;
int c = a +b;
System.out.println("method a");
}
public static void b(){
b();
System.out.println("method b");
}
public static void main(String []args){
b();
System.out.println("method main");
}
}
3.本地方法棧native method stack
作用於本地方法執行的一塊內存區域
各類native方法,JUC包中的CAS
hotspot (JVM) 將java虛擬機棧和本地方法棧合二爲一,hotspot只是java內存模型的其中一種實踐
4.java堆
是java內存區域中一塊用來存放對象實例的區域,幾乎所有的對象實例都在這裏分配內存
此內存區域唯一目的就是存放對象
java堆是虛擬機管理的內存中最大的一塊內存,java堆內存被所有線程共享
特點:
java堆內存是垃圾回收器管理的主要區域,很多時候也被稱爲GC堆,垃圾堆
可以在項目啓動前對堆內存進行配置
-Xmx -Xms
堆內存可以分爲新生代,老年代,新生代又分爲to space,from space,end space
5.方法區
是什麼?
它用於存儲類信息,常量,靜態變量,即時編譯器編譯後的代碼等數據
類信息:類的版本號,方法,接口
爲什麼存在?
內存中存放類信息等數據,屬於線程共享的一塊區域
hotspot使用永久代來實現方法區,在jrockit ,j9vm等虛擬機中沒有這個概念
特點?
並非數據放入方法區就如永久代名字一樣永久,這塊區域回收目標的主要針對常量池的回收和對類型的卸載
無法滿足內存分配的需求時,方法區也會拋出outmemoryError
6.運行時常量池
是什麼?
運行時常量池是方法區的一部分,class文件除了除了有類的版本,字段,方法,接口等描述信息,還有
一項常量池,用於存放編譯器生成的各種字面量和符號引用,這部分內存將在類加載後進入方法區的
運行時常量池中存放
驗證字符串內存中的位置:
/**
* @Auther: jorian
* @Date: 2019/7/10 22:37
* @Description:
*/
public class B {
public static void main(String []args){
String a = "abc";
String b = "abc";
System.out.println(a==b);
String c = new String("abc");
System.out.println(a==c);
System.out.println(c.intern());//將c的內存從堆移到了運行時常量池
}
}
特點?
運行時常量池是方法區的一部分,所以同樣受到方法區內存的限制,同樣會有outMemoryError