原文地址:http://yanwushu.sinaapp.com/java_data_storage/
Java程序在運(yùn)行時(shí)需要為1系列的值或?qū)ο蠓峙鋬?nèi)存,這些值都存在甚么地方?用甚么樣的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)?這些數(shù)據(jù)結(jié)構(gòu)有甚么特點(diǎn)?本文試圖說明此命題的皮毛之皮毛。
概念
對(duì)Java,有6個(gè)不同的、用于數(shù)據(jù)存儲(chǔ)的概念,他們是:
1. 寄存器( register),是最快的存儲(chǔ)區(qū),位于處理器內(nèi)部。由于寄存器的數(shù)量極為有限,所以寄存器由編譯器根據(jù)需求進(jìn)行分配。http://www.jyygyx.com沒法使用Java代碼使用寄存器中的存儲(chǔ)空間,或說:在Java開發(fā)的層面上,寄存器的操作已被封裝。
2. 棧( stack),位于通用 RAM。存取速度快,僅次于寄存器。棧指針若向下移動(dòng),則分配新的內(nèi)存;若向上移動(dòng),則釋放那些內(nèi)存。創(chuàng)建程序時(shí)候, JAVA 編譯器必須知道存儲(chǔ)在棧內(nèi)所有數(shù)據(jù)的確切大小和生命周期,由于它必須生成相應(yīng)的代碼,以便上下移動(dòng)棧指針,進(jìn)而分配和釋放內(nèi)存。由于棧的這類存儲(chǔ)特性,所以某些數(shù)據(jù)存在棧中,比如對(duì)象援用和基礎(chǔ)類型的變量值;但是有些數(shù)據(jù)是不合適存到棧中的,比如對(duì)象的實(shí)例。
3. 堆( heap),1個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),位于 RAM。堆中的空間是動(dòng)態(tài)分配的,所以,不需要知道數(shù)據(jù)的大小和生命周期。因此,在堆里存儲(chǔ)數(shù)據(jù)有很大的靈活性。Java對(duì)象的實(shí)例和數(shù)組放在這里。堆中的過期對(duì)象由GC負(fù)責(zé)回收。堆的存取速度較慢。
4. 靜態(tài)存儲(chǔ)( static storage),RAM中1片固定的位置。存儲(chǔ)靜態(tài)數(shù)據(jù),這些數(shù)據(jù)在程序中用static關(guān)鍵字修飾。
5. 常量存儲(chǔ)( constant storage),常量值通常直接寄存在程序代碼內(nèi)部,這樣做是安全的,由于它們永久不會(huì)被改變。
6. 非 RAM存儲(chǔ)。如果數(shù)據(jù)完全存活于程序以外,那末它可以不受程序的任何控制,在程序沒有運(yùn)行時(shí)也能夠存在。
棧和靜態(tài)存儲(chǔ)的數(shù)據(jù)同享
用1個(gè)案例理解,假定定義:
int a = 3;
int b = 3 ;
編譯器先處理 int a = 3 ;首先它會(huì)在棧中創(chuàng)建1個(gè)變量為a 的援用,然后查找棧中是不是有 3 這個(gè)值,如果沒找到,就將3 寄存進(jìn)來,然后將 a 指向 3 。接著處理 int b = 3 ;在創(chuàng)建完 b 的援用變量后,由于在棧中已有 3 這個(gè)值,便將 b 直接指向 3 。這樣,就出現(xiàn)了 a 與 b 同時(shí)均指向 3 的情況。這時(shí)候,如果再令 a=4 ;那末編譯器會(huì)重新搜索棧中是不是有 4 值,如果沒有,則將 4 寄存進(jìn)來,并令 a 指向 4 ;如果已有了,則直接將 a 指向這個(gè)地址。因此 a 值的改變不會(huì)影響到 b 的值。要注意這類數(shù)據(jù)的同享與兩個(gè)對(duì)象的援用同時(shí)指向1個(gè)對(duì)象的這類同享是不同的,由于這類情況 a 的修改其實(shí)不會(huì)影響到 b, 它是由編譯器完成的,它有益于節(jié)省空間。而1個(gè)對(duì)象援用變量修改了這個(gè)對(duì)象的內(nèi)部狀態(tài),會(huì)影響到另外一個(gè)對(duì)象援用變量。
數(shù)據(jù)同享對(duì)靜態(tài)數(shù)據(jù)一樣。