新聞中心
內(nèi)存分配以及回收
Java虛擬機(jī)運(yùn)行時數(shù)據(jù)區(qū),分為以下幾個模塊,包含所有線程共有的數(shù)據(jù)區(qū)和線程單獨(dú)享有的數(shù)據(jù)區(qū)。
- 程序計數(shù)器:字節(jié)碼行號,通過這個計數(shù)器來選取下一條需要執(zhí)行的指令,線程獨(dú)有。
- 虛擬機(jī)棧:線程私有。方法在執(zhí)行時會創(chuàng)建一個棧幀,用于存儲局部變量表等。局部變量表中存放了編譯器可知的基本數(shù)據(jù)類型、對象引用、returnAddress(指向了一條字節(jié)碼指令的地址)
- 本地方法棧:與虛擬機(jī)棧類似,只不過這個地方是為native方法服務(wù)。
- 堆:線程共用。存放對象實例。
- 方法區(qū):線程共用。存儲已經(jīng)被虛擬機(jī)加載的類信息、常量、靜態(tài)變量等。
- 運(yùn)行時常量池:用于存放編譯期生成的字面量和符合引用。字面量就是我們所說的常量概念,如文本字符串、被聲明為final的常量值等。符號引用是一組符號來描述所引用的目標(biāo),符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標(biāo)即可,一般包括下面三類常量:類和接口的全限定名、字段的名稱和描述符、方法的名稱和描述符。

JVM通過根搜索算法來判定對象是否可以回收,一般對于不能從根(GC Roots)搜索到的對象是可以被回收的。
能夠被作為GC Roots對象有:虛擬機(jī)棧本地變量表中引用的對象(也就是正在調(diào)用的方法中引用的);方法區(qū)中靜態(tài)屬性或常量引用的對象;本地方法棧引用的對象。
可以被回收的對象并不一定絕對被回收,JVM先做一次標(biāo)記和篩選,把那些覆蓋了finalize方法的對象篩選出來然后觸發(fā)finalize方法,如果在finalize方法中對象復(fù)活,則不回收,否則回收,且finalize方法僅會被觸發(fā)一次。
垃圾回收算法
- 標(biāo)記-清除:把標(biāo)記為待回收的對象空間清除,容易造成大量空間碎片;
- 復(fù)制算法:將內(nèi)存分為三個區(qū)域,一個較大的eden區(qū)和兩個較小的survivor區(qū)。每次GC都把存活的對象挪到其中一個servivor區(qū),然后把eden全部清除。只對每次GC時存活對象較少時比較有效,適用于新生代;
- 標(biāo)記-整理:把標(biāo)記后存活的對象向一個方向移動,然后清除其它空間。比較適合老年代。
內(nèi)存分配與回收策略
- 對象默認(rèn)優(yōu)先分配在新生代;
- 大對象直接分配到老年代;
- 長期存活的對象轉(zhuǎn)移到老年代:虛擬機(jī)給每個對象定義一個對象年齡,沒發(fā)生一次minor GC,年齡就增加一次,超過默認(rèn)值之后就會進(jìn)入到老年代。
- 動態(tài)對象年齡判定:對象不一定是必須到了默認(rèn)年齡才能進(jìn)入老年代,如果一個eden區(qū)中所有相同年齡的對象大小綜合超過eden一半的空間,那么大于等于這個年齡的對象也會進(jìn)入老年代。
類文件結(jié)構(gòu)
class文件是二進(jìn)制組成的,class有兩種數(shù)據(jù)類型:無符號數(shù)和表。
無符號數(shù)是基礎(chǔ)數(shù)據(jù)類型,其中u1表示1個字節(jié)、u2表示2個字節(jié)(一個字節(jié)8個bit,而4個bit可以表示1個16進(jìn)制的數(shù),也就是說1個字節(jié)可以用2個16進(jìn)制數(shù)表示);
表是由多個無符號數(shù)或其它表構(gòu)成的。
- magic是4個字節(jié),也就是8個16進(jìn)制數(shù),固定為CAFEBABE;后面分別是兩個版本號。
- 常量池:跟著版本號之后的就是常量池(字面量和符號引用)。由于無法確認(rèn)一個類中常量池有多少常量,所有先有一個值來標(biāo)志有多少個,然后再是常量具體信息。
- 訪問標(biāo)志:常量池之后跟著的是2個字節(jié)的訪問標(biāo)志。需要被標(biāo)志的內(nèi)容包括:是否public、是否final、是否abstract、是類或接口
- 訪問標(biāo)志之后是類索引(用于確定該類的全限定名)、父類索引(用于確定父類的全限定名)、接口所有集合(實現(xiàn)的接口可能不止一個)
- 字段表集合:描述接口或類中聲明的變量,包含類變量和實例變量。
- 方法表集合:描述類或接口中聲明的fangfa。
- 屬性表結(jié)合:
code屬性:java方法體中的代碼經(jīng)javac編譯后會存儲在code屬性中(接口中方法或抽象方法沒有code屬性)
Exceptions屬性:列舉出方法throws后面拋出的異常;
其它各屬性不再一一列舉。
類加載機(jī)制

類加載的時機(jī)
主動引用的幾種情況才會加載(前提是此類沒有被加載過)
- new一個對象、引用類的static變量(final變量除外)、調(diào)用類的static方法;
- 對類進(jìn)行反射調(diào)用時;
- 初始化一個類時,如果父類沒有被初始化,則先初始化父類;
- 虛擬機(jī)啟動時,初始化包含main方法的那個類
被動引用不會觸發(fā)初始化
- 調(diào)用父類靜態(tài)方法,不會初始化子類;
- 通過數(shù)組定義引用類,不會觸發(fā)初始化;
- 引用靜態(tài)常量不會觸發(fā)。
加載過程
- 通過一個類全限定名獲取定義此類的二進(jìn)制字節(jié)流(一般是class文件)
- 將二進(jìn)制字節(jié)流轉(zhuǎn)化為方法區(qū)中的運(yùn)行時數(shù)據(jù)結(jié)構(gòu)
- 在內(nèi)存(堆)中生成這個類的Class類的對象,作為方法區(qū)這個類的各個數(shù)據(jù)的訪問入口
連接過程
- 驗證階段:文件格式驗證(是否符合Class文件規(guī)范)、元數(shù)據(jù)驗證(是否符合java語法規(guī)范)、字節(jié)碼驗證(確保語義是符合邏輯的)、符合引用驗證。
- 準(zhǔn)備階段:正式為類變量分配內(nèi)存并設(shè)置初始值。
有兩點(diǎn)需要注意:
一,此處只為類變量分配內(nèi)存(static修飾的),不包含實例變量;
二,設(shè)置的初始值是這個類型的0值,不是實際值(但被final修飾的賦的就是實際值) - 解析階段:將符合引用替換為直接引用
初始化過程
初始化過程主要是執(zhí)行類構(gòu)造器
方法主要是手機(jī)所有類變量的賦值動作,和靜態(tài)語句塊(staic {}); - 虛擬機(jī)會保證
方法在父類中先調(diào)用,這樣說明父類的static語句塊要比子類的static變量賦值操作先執(zhí)行,以下代碼中,字段B的值將會是2 
- 這也說明了一個問題:new一個對象時,靜態(tài)變量賦值和靜態(tài)語句塊會在類的構(gòu)造方法前執(zhí)行。
類加載器
- 比較兩個類對象是否相等,只有加載兩個類加載器的完全一樣,才有意義;
- 如果一個類加載器收到一個類加載請求,它首先會請求委派給父類加載器完成,父類無法完成時,子類加載器才進(jìn)行加載。
虛擬機(jī)字節(jié)碼執(zhí)行引擎

運(yùn)行時棧幀結(jié)構(gòu)
- 局部變量表:存放方法參數(shù)和局部變量。每個變量以slot為單位,slot可以復(fù)用
注意,如果沒有int a = 0這一行代碼,placeholder是不會被回收的,因為如果不加這行代碼,就沒有任何對局部變量表的讀寫操作,這個slot就不會被占用。 - 操作數(shù)棧:方法執(zhí)行過程中,會有各種字節(jié)碼出棧入棧
- 動態(tài)鏈接:一部分符合引用在類加載時轉(zhuǎn)化為直接引用,這是靜態(tài)機(jī)械;而一部分則是運(yùn)行時轉(zhuǎn)化為直接應(yīng)用,這叫動態(tài)鏈接
方法調(diào)用和分派
- 所有的方法在Class文件中都是一個符合引用,而一部分方法在類加載時就直接解析為直接引用。這種方法必須是“編譯時已知,運(yùn)行時不可變”,就是靜態(tài)方法和私有方法兩大類
- 靜態(tài)分派:依賴靜態(tài)類型來定位方法執(zhí)行版本稱為靜態(tài)分派,典型應(yīng)用是重載。

Human是靜態(tài)類型,后面的Man和Women則是實際類型。
靜態(tài)類型在編譯器可知,而動態(tài)類型則是在運(yùn)行時才能知道。 - 動態(tài)分派:運(yùn)行期間根據(jù)實際類型來確定方法執(zhí)行版本,典型應(yīng)用是覆蓋。

結(jié)果是
內(nèi)存模型及線程安全

JMM規(guī)定所有內(nèi)存都存儲于主內(nèi)存中,每條線程還有自己的工作內(nèi)存。
變量的讀取、賦值操作必須在工作內(nèi)存中進(jìn)行。
內(nèi)存直接的交互操作,主要有以下8種操作:

8種操作需要滿足以下規(guī)則
volatile關(guān)鍵字
- volatile關(guān)鍵字保證了變量的所有線程的可見性,但并非是線程安全的。
兩種情況下是線程不安全的:
一,變量依賴于自身(比如i++之類的)
二,變量依賴于其它變量(比如i=a+3) - volatile禁止語義重排序
- volatile的具體實現(xiàn)

創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務(wù)器買多久送多久。
新聞名稱:Java虛擬機(jī)-創(chuàng)新互聯(lián)
URL分享:http://www.dlmjj.cn/article/coiics.html


咨詢
建站咨詢
