在C++領域,關于C++的內存存儲,結構等等,有一本書:深度探索C++對象模型,講解的非常透徹。
而java確把這一工作交給了虛擬機來處理。
我們首先來看看關于內存的問題。
1.問題:
1)java 的局部變量存在那里,類型怎么存放的?
2)static 變量
3)final 變量
4)method是存放的那里的
5)class類 & 內部類 是如何存放
2.java虛擬機運行是數據區
2.1程序計數器
線程隔離數據,記錄當前線程執行的位置。
PC計數器
由于Java虛擬機的多線程,是由線程輪換的方式分配CPU的。所以線程切換后,需要恢復到原來執行的地方
沒有線程都需要一塊內存來記錄這個執行位置,此內存是線程私有的。
2.2Java虛擬機棧
這個棧就是我們常見的java 面試題中一般會問 heap & stack 的區別。 這里的stack就是我們說的虛擬機棧。
這個棧是存放每個method執行的時候的局部變量表,動態連接,方法出口等信息。
局部變量表存放:局部變量類型,已經基本類型的變量。
棧中可以理解為存放對象的引用,為對象本身存放在堆。
如果申請的內存不夠,就會OOM。
2.3本地方法棧
這個東西同Java虛擬機棧非常類似,這里存放這native方法的一些信息。
2.4Java堆
千呼萬喚始出來,對象實例就是存放在這個地方。也是java內存最大的地方。
GC的主要工作就是釋放這里不用的內存。
這塊區域為所有線程共享。所以android就會有activity或者service在非前臺狀態下,是否低優先級的情況。
2.5方法區
這塊地方存放的就是已經加載的類信息,靜態變量,常量等。
String abc = “abc”; 這后面的“abc”就存放在這里。
2.5.2 運行時常量區
java在非編譯階段,也可以是一種常量的形式,比如:
String str = "abc"+"d";
它會生成“abcd”常量在運行時候。
3.HotStot虛擬機對象探秘
java對象的創建過程分成2步:
1)加載類信息,存放在方法區
2)根據類信息,分配內存存放對象,內存在堆區。
分配內存的常見方式:
1)假設內存在堆區分為2塊,一塊是已經在使用的,一塊是還沒有分配的,這樣我只要設置一個指針,來區分這兩塊區域。
當分配新的內存時,移動指針即可。
2)內存區域是不連續的,這樣我只能在空閑的內存中,找到一塊足夠大的內存來分配,這種為空閑列表的方式。
但是,當分配內存時,會有同步的問題。
要么保證分配操作是原子操作,或者就是給每個線程優先分配一小塊內存(Thread Local Allocation Buffer)
這個東西在android looper機制的時候,有所體現。
接下來就是對對象進行設置:
對象是那個類的實例,如何才找到對象的元數據信息,對象的hash表,對象的GC分布年齡等。
從程序員的角度看,一個對象在內存中已經創建,但是init的方法還沒有執行。對象還沒有按照程序員的意愿進行初始化。
3.1 對象的內存布局
在HotStot中,對象的布局可以分為3塊:對象頭,實例數據,和對其填充。
對象頭根據虛擬機的位數,32bit或者64bit。
這部分被以極限的算法,來存儲不少的信息。
實例數據部分,存的是真正有效的信息,這部分會存父類的信息和子類的信息。
3.2對象的訪問方式
reference 指向的是另一個類的對象,所以它指向的實際是堆中的另一塊內存而已。

HotSopt使用的是第二種方式。
新聞熱點
疑難解答