java資料儲存
記錄一下java中的資料儲存:
這是我參考的文章:
https://blog.csdn.net/futurech/article/details/73699652 、
https://blog.csdn.net/zhangbaoanhadoop/article/details/82193497 、
https://blog.csdn.net/qq_32127759/article/details/80725115
在《thinking in java》這本書的第二章也有提到,因為涉及到jvm(我還沒看),這個等我之後再補充。
一、六種不同的資料儲存
1. 暫存器(register)。這是最快的儲存區,因為它位於不同於其他儲存區的地方——處理器內部。但是暫存器的數量極其有限,所以暫存器由編譯器根據需求進行分配。你不能直接控制,也不能在程式中感覺到暫存器存在的任何跡象。(暫存器的使用是在JVM中討論的,等我看到這部分的時候再進行補充,用於管理系統堆疊。)
2. 堆疊(stack)。位於通用RAM中,但通過它的“堆疊指標”可以從處理器哪裡獲得支援。堆疊指標若向下移動,則分配新的記憶體;若向上移動,則釋放那些記憶體。這是一種快速有效的分配儲存方法,僅次於暫存器。建立程式時候,JAVA編譯器必須知道儲存在堆疊內所有資料的確切大小和生命週期,因為它必須生成相應的程式碼,以便上下移動堆疊指標。這一約束限制了程式的靈活性,所以雖然某些JAVA資料儲存在堆疊中——特別是物件引用和基本資料型別,但是JAVA物件不儲存其中。
3. 堆(heap)。一種通用性的記憶體池(也存在於RAM中),用於存放所以的JAVA物件。堆不同於堆疊的好處是:編譯器不需要知道要從堆裡分配多少儲存區域,也不必知道儲存的資料在堆裡存活多長時間。因此,在堆裡分配儲存有很大的靈活性。當你需要建立一個物件的時候,只需要new寫一行簡單的程式碼,當執行這行程式碼時,會自動在堆裡進行儲存分配。當然,為這種靈活性必須要付出相應的程式碼。用堆進行儲存分配比用堆疊進行儲存儲存需要更多的時間。
4. 靜態儲存(static storage)。也叫方法區,包含整個程式中永遠唯一的元素,比如static和class。
這裡的“靜態”是指“在固定的位置”。靜態儲存裡存放程式執行時一直存在的資料。你可用關鍵字static來標識一個物件的特定元素是靜態的,但JAVA物件本身從來不會存放在靜態儲存空間裡。
注意,static不能修飾區域性變數。static final 修飾的成員變數在常量儲存區,僅僅static修飾的成員變數在靜態儲存區。
5. 常量儲存(constant storage)。常量值通常直接存放在程式程式碼內部,這樣做是安全的,因為它們永遠不會被改變。有時,在嵌入式系統中,常量本身會和其他部分分割離開,所以在這種情況下,可以選擇將其放在ROM中
6. 非RAM儲存。如果資料完全存活於程式之外,那麼它可以不受程式的任何控制,在程式沒有執行時也可以存在。比如流物件和持久化物件(儲存在磁碟,磁帶上的資料)
就速度來說,有如下關係:
暫存器 > 堆疊 > 堆 > 其他
二、棧、堆、方法區儲存的內容
堆區:
1.儲存的全部是物件,每個物件都包含一個與之對應的class的資訊。(class的目的是得到操作指令)
2.jvm只有一個堆區(heap)被所有執行緒共享,堆中不存放基本型別和物件引用,只存放物件本身 。
3.動態記憶體,其中的記憶體在不需要時可以回收,以分配給新的記憶體請求,其記憶體中的資料是無序的,即先分配的和隨後分配的記憶體並沒有什麼必然的位置關係,釋放時也可以沒有先後順序。不需要知道資料的生存週期。
棧區:
1.每個執行緒包含一個棧區(可以理解為為每個方法分配了一個小的棧,儲存區域性變數,當方法結束時釋放棧),棧中只儲存基礎資料型別的值和物件以及基礎資料的引用
2.每個棧中的資料(基礎資料型別和物件引用)都是私有的,其他棧不能訪問。
3.棧分為3個部分:基本型別變數區、執行環境上下文、操作指令區(存放操作指令)。
4.棧中的資料生存週期時編譯器已知的
5.棧中的資料時共享的,即兩個基礎型別變數如果值相同的話,實際上是可以指向同一塊資料塊(eg:int a=3,int b=3;a,b指向同一地址),但是不會產生物件引用帶來的一個引用修改另外的引用同時修改(eg,a=4,會重新在棧中尋找是否有一塊記憶體塊值為4)。
方法區:
1.又叫靜態區,跟堆一樣,被所有的執行緒共享。方法區包含所有的class和static變數。
2.方法區中包含的都是在整個程式中永遠唯一的元素,如class,static變數。