深入理解Java內存分配
每當運行一個Java程序時,都會生成一個Java進程,其中可能包含一個或多個線程。每個Java進程對應唯一一個JVM實例,而每個JVM實例又對應唯一的堆,同時每個線程都有自己私有的棧。在Java中,堆
每當運行一個Java程序時,都會生成一個Java進程,其中可能包含一個或多個線程。每個Java進程對應唯一一個JVM實例,而每個JVM實例又對應唯一的堆,同時每個線程都有自己私有的棧。在Java中,堆內存的分配是自動初始化的,即在為對象分配內存時,會初始化這個對象中的變量。盡管所有對象的存儲空間都在堆中進行分配,但對象的引用卻是在棧中分配。接下來我們來詳細了解一下Java如何進行內存分配。
JVM內存劃分概念
JVM的內存可分為三個區(qū)域:堆(heap)、棧(stack)和方法區(qū)(method,也稱為靜態(tài)區(qū))。JVM將其內存劃分為五個區(qū)域:
- 寄存器:用于內存和CPU之間的通信。
- 本地方法棧:用于JVM調用系統(tǒng)功能。
- 方法和數(shù)據共享:運行時期class文件所在位置。
- 方法棧:存儲所有方法運行時期的內存。
- 堆(heap):用于存儲容器和對象。
堆區(qū)
在堆區(qū)存儲的全部是對象,每個對象都包含一個與之對應的class信息,而class的目的是獲取操作指令。JVM只有一個堆區(qū),并且被所有線程共享。堆中不存放基本類型和對象引用,而是僅存放對象本身和數(shù)組本身。
棧區(qū)
每個線程包含一個棧區(qū),棧中只保存基礎數(shù)據類型本身和自定義對象的引用。棧中的數(shù)據(原始類型和對象引用)都是私有的,其他棧不能訪問。棧分為三個部分:基本類型變量區(qū)、執(zhí)行環(huán)境上下文、操作指令區(qū)(存放操作指令)。
方法區(qū)(靜態(tài)區(qū))
方法區(qū)被所有線程共享,其中包含所有的class(類的原始代碼,在創(chuàng)建類的對象時,需要將該類的代碼加載到方法區(qū)并進行初始化)和static變量。方法區(qū)中包含的元素在整個程序中都是唯一的,如class和static變量。
Java虛擬機啟動過程
當運行Java程序時,首先會啟動一個Java虛擬機進程。該進程會從classpath中找到相應的.class文件,讀取其中的二進制數(shù)據,并將類信息存儲到方法區(qū)中,這便是類的加載過程。隨后,Java虛擬機定位到方法區(qū)中相應類的方法字節(jié)碼,開始執(zhí)行指令。在main()方法中,第一條語句即可開始執(zhí)行。