成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

類的加載機(jī)制

mikyou / 611人閱讀

摘要:如果沒有,那必須先執(zhí)行相應(yīng)的類加載過程。分配內(nèi)存在類加載檢查通過后,接下來虛擬機(jī)將為新生對(duì)象分配內(nèi)存。程序計(jì)數(shù)器主要有兩個(gè)作用字節(jié)碼解釋器通過改變程序計(jì)數(shù)器來依次讀取指令,從而實(shí)現(xiàn)代碼的流程控制,如順序執(zhí)行選擇循環(huán)異常處理。

目錄介紹

01.Java對(duì)象的創(chuàng)建過程

1.0 看下創(chuàng)建類加載過程

1.1 對(duì)象的創(chuàng)建

1.2 對(duì)象的內(nèi)存布局

02.Java內(nèi)存區(qū)域

2.0 運(yùn)行時(shí)數(shù)據(jù)區(qū)域

2.1 程序計(jì)數(shù)器

2.2 虛擬機(jī)棧

2.3 本地方法棧

2.4 Java堆

2.5 方法區(qū)

2.6 運(yùn)行時(shí)常量池

2.7 直接內(nèi)存

03.Java對(duì)象的訪問定位方式

3.1 句柄

3.2 直接指針

04.Java對(duì)象銷毀分析

4.1 JVM內(nèi)存分配與回收

4.2 判斷對(duì)象是否死亡

4.3 不可達(dá)的對(duì)象并非“非死不可”

4.4 如何判斷一個(gè)常量是廢棄常量

4.5 如何判斷一個(gè)類是無用的類

4.6 GC回收算法詳解

05.String類和常量池

5.1 String對(duì)象的兩種創(chuàng)建方式

5.2 String類型的常量池

好消息

博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識(shí)點(diǎn),Android技術(shù)博客,Python學(xué)習(xí)筆記等等,還包括平時(shí)開發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題,長(zhǎng)期更新維護(hù)并且修正,持續(xù)完善……開源的文件是markdown格式的!同時(shí)也開源了生活博客,從12年起,積累共計(jì)47篇[近20萬字],轉(zhuǎn)載請(qǐng)注明出處,謝謝!

鏈接地址:https://github.com/yangchong2...

如果覺得好,可以star一下,謝謝!當(dāng)然也歡迎提出建議,萬事起于忽微,量變引起質(zhì)變!

問題思考答疑

說一下創(chuàng)建一個(gè)對(duì)象,類的加載過程。類信息,常量,變量,方法分別放到內(nèi)存中哪里?

對(duì)于運(yùn)行時(shí)數(shù)據(jù)區(qū)域,哪些是私有的,哪些是共享的,為什么要這樣設(shè)計(jì)?

程序計(jì)數(shù)器會(huì)出現(xiàn)OOM嗎?它的生命周期是怎么樣的?

本地方法棧和Java虛擬機(jī)棧有什么區(qū)別?本地方法棧在什么情況下會(huì)造成OOM?

java堆主要是做什么作用的?

什么是類的加載檢查,主要檢查什么,如何檢查呢?

Java對(duì)象訪問定位方式有哪些?主要有什么區(qū)別?為什么說使用指針效率更高?

String類可以new嗎?直接new和賦值的內(nèi)容有什么區(qū)別,分別放在內(nèi)存中什么地方?

如何判斷對(duì)象是否死亡(兩種方法)。如果有不同方法,那么之間有什么區(qū)別?

簡(jiǎn)單的介紹一下強(qiáng)引用、軟引用、弱引用、虛引用(虛引用與軟引用和弱引用的區(qū)別、使用軟引用能帶來的好處)。

如何判斷一個(gè)常量是廢棄常量,如何判斷一個(gè)類是無用的類?

垃圾收集有哪些算法,各自的特點(diǎn)?常見的垃圾回收器有那些?

HotSpot為什么要分為新生代和老年代?

介紹一下CMS,G1收集器。Minor Gc和Full GC 有什么不同呢?

01.Java對(duì)象的創(chuàng)建過程 1.1 看下創(chuàng)建類加載過程

Person p = new Person()請(qǐng)寫一下類的加載過程?

1).因?yàn)閚ew用到了Person.class,所以會(huì)先找到Person.class文件,并加載到內(nèi)存中;
2).執(zhí)行該類中的static代碼塊,如果有的話,給Person.class類進(jìn)行初始化;
3).在堆內(nèi)存中開辟空間分配內(nèi)存地址;
4).在堆內(nèi)存中建立對(duì)象的特有屬性,并進(jìn)行默認(rèn)初始化;
5).對(duì)屬性進(jìn)行顯示初始化;
6).對(duì)對(duì)象進(jìn)行構(gòu)造代碼塊初始化;
7).對(duì)對(duì)象進(jìn)行與之對(duì)應(yīng)的構(gòu)造函數(shù)進(jìn)行初始化;
8).將內(nèi)存地址付給棧內(nèi)存中的p變量

1.1 對(duì)象的創(chuàng)建

Java對(duì)象的創(chuàng)建過程,我建議最好是能默寫出來,并且要掌握每一步在做什么。

1.類加載檢查

2.分配內(nèi)存

3.初始化零值

4.設(shè)置對(duì)象頭

5.執(zhí)行init方法

①類加載檢查:

虛擬機(jī)遇到一條 new 指令時(shí),首先將去檢查這個(gè)指令的參數(shù)是否能在常量池中定位到這個(gè)類的符號(hào)引用,并且檢查這個(gè)符號(hào)引用代表的類是否已被加載過、解析和初始化過。如果沒有,那必須先執(zhí)行相應(yīng)的類加載過程。

②分配內(nèi)存:

類加載檢查通過后,接下來虛擬機(jī)將為新生對(duì)象分配內(nèi)存。對(duì)象所需的內(nèi)存大小在類加載完成后便可確定,為對(duì)象分配空間的任務(wù)等同于把一塊確定大小的內(nèi)存從 Java 堆中劃分出來。分配方式“指針碰撞”“空閑列表” 兩種,選擇那種分配方式由 Java 堆是否規(guī)整決定,而Java堆是否規(guī)整又由所采用的垃圾收集器是否帶有壓縮整理功能決定。

內(nèi)存分配的兩種方式:

選擇以上兩種方式中的哪一種,取決于 Java 堆內(nèi)存是否規(guī)整。而 Java 堆內(nèi)存是否規(guī)整,取決于 GC 收集器的算法是"標(biāo)記-清除",還是"標(biāo)記-整理"("標(biāo)記-壓縮"),值得注意的是,復(fù)制算法內(nèi)存也是規(guī)整的

內(nèi)存分配并發(fā)問題

在創(chuàng)建對(duì)象的時(shí)候有一個(gè)很重要的問題,就是線程安全,因?yàn)樵趯?shí)際開發(fā)過程中,創(chuàng)建對(duì)象是很頻繁的事情,作為虛擬機(jī)來說,必須要保證線程是安全的,通常來講,虛擬機(jī)采用兩種方式來保證線程安全:

CAS+失敗重試:

CAS 是樂觀鎖的一種實(shí)現(xiàn)方式。所謂樂觀鎖就是,每次不加鎖而是假設(shè)沒有沖突而去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試,直到成功為止。虛擬機(jī)采用 CAS 配上失敗重試的方式保證更新操作的原子性。

TLAB:

為每一個(gè)線程預(yù)先在Eden區(qū)分配一塊兒內(nèi)存,JVM在給線程中的對(duì)象分配內(nèi)存時(shí),首先在TLAB分配,當(dāng)對(duì)象大于TLAB中的剩余內(nèi)存或TLAB的內(nèi)存已用盡時(shí),再采用上述的CAS進(jìn)行內(nèi)存分配

③初始化零值:

內(nèi)存分配完成后,虛擬機(jī)需要將分配到的內(nèi)存空間都初始化為零值(不包括對(duì)象頭),這一步操作保證了對(duì)象的實(shí)例字段在 Java 代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數(shù)據(jù)類型所對(duì)應(yīng)的零值。

④設(shè)置對(duì)象頭:

初始化零值完成之后,虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置,例如這個(gè)對(duì)象是那個(gè)類的實(shí)例、如何才能找到類的元數(shù)據(jù)信息、對(duì)象的哈希嗎、對(duì)象的 GC 分代年齡等信息。

這些信息存放在對(duì)象頭中。 另外,根據(jù)虛擬機(jī)當(dāng)前運(yùn)行狀態(tài)的不同,如是否啟用偏向鎖等,對(duì)象頭會(huì)有不同的設(shè)置方式。

⑤執(zhí)行 init 方法:

在上面工作都完成之后,從虛擬機(jī)的視角來看,一個(gè)新的對(duì)象已經(jīng)產(chǎn)生了,但從 Java 程序的視角來看,對(duì)象創(chuàng)建才剛開始, 方法還沒有執(zhí)行,所有的字段都還為零。所以一般來說,執(zhí)行 new 指令之后會(huì)接著執(zhí)行 方法,把對(duì)象按照程序員的意愿進(jìn)行初始化,這樣一個(gè)真正可用的對(duì)象才算完全產(chǎn)生出來。

1.2 對(duì)象的內(nèi)存布局

在 Hotspot 虛擬機(jī)中,對(duì)象在內(nèi)存中的布局可以分為3快區(qū)域:對(duì)象頭、實(shí)例數(shù)據(jù)對(duì)齊填充。

Hotspot虛擬機(jī)的對(duì)象頭包括兩部分信息第一部分用于存儲(chǔ)對(duì)象自身的自身運(yùn)行時(shí)數(shù)據(jù)(哈希嗎、GC分代年齡、鎖狀態(tài)標(biāo)志等等),另一部分是類型指針,即對(duì)象指向它的類元數(shù)據(jù)的指針,虛擬機(jī)通過這個(gè)指針來確定這個(gè)對(duì)象是那個(gè)類的實(shí)例。

實(shí)例數(shù)據(jù)部分是對(duì)象真正存儲(chǔ)的有效信息,也是在程序中所定義的各種類型的字段內(nèi)容。

對(duì)齊填充部分不是必然存在的,也沒有什么特別的含義,僅僅起占位作用。

因?yàn)镠otspot虛擬機(jī)的自動(dòng)內(nèi)存管理系統(tǒng)要求對(duì)象起始地址必須是8字節(jié)的整數(shù)倍,換句話說就是對(duì)象的大小必須是8字節(jié)的整數(shù)倍。而對(duì)象頭部分正好是8字節(jié)的倍數(shù)(1倍或2倍),因此,當(dāng)對(duì)象實(shí)例數(shù)據(jù)部分沒有對(duì)齊時(shí),就需要通過對(duì)齊填充來補(bǔ)全。

02.Java內(nèi)存區(qū)域 2.0 運(yùn)行時(shí)數(shù)據(jù)區(qū)域

Java 虛擬機(jī)在執(zhí)行 Java 程序的過程中會(huì)把它管理的內(nèi)存劃分成若干個(gè)不同的數(shù)據(jù)區(qū)域。

這些組成部分一些事線程私有的,其他的則是線程共享的。

線程私有的:

程序計(jì)數(shù)器

虛擬機(jī)棧

本地方法棧

線程共享的:

Java堆

方法區(qū)

運(yùn)行時(shí)常量池

直接內(nèi)存

2.1 程序計(jì)數(shù)器

程序計(jì)數(shù)器:是一個(gè)數(shù)據(jù)結(jié)構(gòu),用于保存當(dāng)前正常執(zhí)行的程序的內(nèi)存地址。Java虛擬機(jī)的多線程就是通過線程輪流切換并分配處理器時(shí)間來實(shí)現(xiàn)的,為了線程切換后能恢復(fù)到正確的位置,每條線程都需要一個(gè)獨(dú)立的程序計(jì)數(shù)器,互不影響,該區(qū)域?yàn)椤熬€程私有”。

程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。字節(jié)碼解釋器工作時(shí)通過改變這個(gè)計(jì)數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復(fù)等功能都需要依賴這個(gè)計(jì)數(shù)器來完。

程序計(jì)數(shù)器主要有兩個(gè)作用:

1.字節(jié)碼解釋器通過改變程序計(jì)數(shù)器來依次讀取指令,從而實(shí)現(xiàn)代碼的流程控制,如:順序執(zhí)行、選擇、循環(huán)、異常處理。

2.在多線程的情況下,程序計(jì)數(shù)器用于記錄當(dāng)前線程執(zhí)行的位置,從而當(dāng)線程被切換回來的時(shí)候能夠知道該線程上次運(yùn)行到哪兒。

注意:程序計(jì)數(shù)器是唯一一個(gè)不會(huì)出現(xiàn)OutOfMemoryError的內(nèi)存區(qū)域,它的生命周期隨著線程的創(chuàng)建而創(chuàng)建,隨著線程的結(jié)束而死亡。

2.2 虛擬機(jī)棧

Java虛擬機(jī)棧:線程私有的,與線程生命周期相同,用于存儲(chǔ)局部變量表,操作棧,方法返回值。局部變量表放著基本數(shù)據(jù)類型,還有對(duì)象的引用。

Java 內(nèi)存可以粗糙的區(qū)分為堆內(nèi)存(Heap)和棧內(nèi)存(Stack),其中棧就是現(xiàn)在說的虛擬機(jī)棧,或者說是虛擬機(jī)棧中局部變量表部分。(實(shí)際上,Java虛擬機(jī)棧是由一個(gè)個(gè)棧幀組成,而每個(gè)棧幀中都擁有:局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口信息。)

局部變量表主要存放了編譯器可知的各種數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對(duì)象引用(reference類型,它不同于對(duì)象本身,可能是一個(gè)指向?qū)ο笃鹗嫉刂返囊弥羔?,也可能是指向一個(gè)代表對(duì)象的句柄或其他與此對(duì)象相關(guān)的位置)。

Java 虛擬機(jī)棧會(huì)出現(xiàn)兩種異常:StackOverFlowError 和 OutOfMemoryError。

StackOverFlowError: 若Java虛擬機(jī)棧的內(nèi)存大小不允許動(dòng)態(tài)擴(kuò)展,那么當(dāng)線程請(qǐng)求棧的深度超過當(dāng)前Java虛擬機(jī)棧的最大深度的時(shí)候,就拋出StackOverFlowError異常。

OutOfMemoryError: 若Java虛擬機(jī)棧的內(nèi)存大小允許動(dòng)態(tài)擴(kuò)展,且當(dāng)線程請(qǐng)求棧時(shí)內(nèi)存用完了,無法再動(dòng)態(tài)擴(kuò)展了,此時(shí)拋出OutOfMemoryError異常。

Java 虛擬機(jī)棧也是線程私有的,每個(gè)線程都有各自的Java虛擬機(jī)棧,而且隨著線程的創(chuàng)建而創(chuàng)建,隨著線程的死亡而死亡。

2.3 本地方法棧

本地方法棧:跟虛擬機(jī)棧很像, 虛擬機(jī)棧為虛擬機(jī)執(zhí)行 Java 方法 (也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機(jī)使用到的 Native 方法服務(wù)。 在 HotSpot 虛擬機(jī)中和 Java 虛擬機(jī)棧合二為一。

本地方法被執(zhí)行的時(shí)候,在本地方法棧也會(huì)創(chuàng)建一個(gè)棧幀,用于存放該本地方法的局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、出口信息。

方法執(zhí)行完畢后相應(yīng)的棧幀也會(huì)出棧并釋放內(nèi)存空間,也會(huì)出現(xiàn) StackOverFlowError 和 OutOfMemoryError 兩種異常。

2.4 Java堆

Java堆:所有線程共享的一塊內(nèi)存區(qū)域,此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例,對(duì)象實(shí)例幾乎都在這分配內(nèi)存。在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。

Java 堆是垃圾收集器管理的主要區(qū)域,因此也被稱作GC堆(Garbage Collected Heap).從垃圾回收的角度,由于現(xiàn)在收集器基本都采用分代垃圾收集算法,所以Java堆還可以細(xì)分為:新生代和老年代:在細(xì)致一點(diǎn)有:Eden空間、From Survivor、To Survivor空間等。進(jìn)一步劃分的目的是更好地回收內(nèi)存,或者更快地分配內(nèi)存。

在 JDK 1.8中移除整個(gè)永久代,取而代之的是一個(gè)叫元空間(Metaspace)的區(qū)域(永久代使用的是JVM的堆內(nèi)存空間,而元空間使用的是物理內(nèi)存,直接受到本機(jī)的物理內(nèi)存限制)。

2.5 方法區(qū)

方法區(qū):各個(gè)線程共享的區(qū)域,儲(chǔ)存虛擬機(jī)加載的類信息,常量,靜態(tài)變量,編譯后的代碼。

雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分,但是它卻有一個(gè)別名叫做 Non-Heap(非堆),目的應(yīng)該是與 Java 堆區(qū)分開來。

相對(duì)而言,垃圾收集行為在這個(gè)區(qū)域是比較少出現(xiàn)的,但并非數(shù)據(jù)進(jìn)入方法區(qū)后就“永久存在”了。如何理解這句話?

2.6 運(yùn)行時(shí)常量池

運(yùn)行時(shí)常量池:代表運(yùn)行時(shí)每個(gè)class文件中的常量表。包括幾種常量:編譯時(shí)的數(shù)字常量、方法或者域的引用。

。Class 文件中包括類的版本、字段、方法、接口等描述信息

既然運(yùn)行時(shí)常量池時(shí)方法區(qū)的一部分,自然受到方法區(qū)內(nèi)存的限制,當(dāng)常量池?zé)o法再申請(qǐng)到內(nèi)存時(shí)會(huì)拋出 OutOfMemoryError 異常。JDK1.7及之后版本的 JVM已經(jīng)將運(yùn)行時(shí)常量池從方法區(qū)中移了出來,在Java堆(Heap)中開辟了一塊區(qū)域存放運(yùn)行時(shí)常量池。

2.7 直接內(nèi)存

直接內(nèi)存并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,也不是虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域,但是這部分內(nèi)存也被頻繁地使用。而且也可能導(dǎo)致OutOfMemoryError異常出現(xiàn)。

JDK1.4中新加入的 NIO(New Input/Output) 類,引入了一種基于通道(Channel)緩存區(qū)(Buffer) 的 I/O 方式,它可以直接使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存,然后通過一個(gè)存儲(chǔ)在 Java 堆中的 DirectByteBuffer 對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣就能在一些場(chǎng)景中顯著提高性能,因?yàn)?strong>避免了在 Java 堆和 Native 堆之間來回復(fù)制數(shù)據(jù)。

本機(jī)直接內(nèi)存的分配不會(huì)收到 Java 堆的限制,但是,既然是內(nèi)存就會(huì)受到本機(jī)總內(nèi)存大小以及處理器尋址空間的限制。

03.Java對(duì)象的訪問定位方式

建立對(duì)象就是為了使用對(duì)象,我們的Java程序通過棧上的 reference 數(shù)據(jù)來操作堆上的具體對(duì)象。對(duì)象的訪問方式有虛擬機(jī)實(shí)現(xiàn)而定

目前主流的訪問方式有

①使用句柄

②直接指針

這兩種對(duì)象訪問方式各有優(yōu)勢(shì)。

使用句柄來訪問的最大好處是 reference 中存儲(chǔ)的是穩(wěn)定的句柄地址,在對(duì)象被移動(dòng)時(shí)只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針,而 reference 本身不需要修改。

使用直接指針訪問方式最大的好處就是速度快,它節(jié)省了一次指針定位的時(shí)間開銷。

3.1 句柄

如果使用句柄的話,那么Java堆中將會(huì)劃分出一塊內(nèi)存來作為句柄池,reference 中存儲(chǔ)的就是對(duì)象的句柄地址,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)與類型數(shù)據(jù)各自的具體地址信息;

3.2 直接指針

如果使用直接指針訪問,那么 Java 堆對(duì)像的布局中就必須考慮如何放置訪問類型數(shù)據(jù)的相關(guān)信息,而reference 中存儲(chǔ)的直接就是對(duì)象的地址。

04.Java對(duì)象銷毀分析

思考一下,更多可以參考我的博客:https://github.com/yangchong2...

4.1 JVM內(nèi)存分配與回收

Java 的自動(dòng)內(nèi)存管理主要是針對(duì)對(duì)象內(nèi)存的回收和對(duì)象內(nèi)存的分配。同時(shí),Java 自動(dòng)內(nèi)存管理最核心的功能是 內(nèi)存中對(duì)象的分配與回收。

JDK1.8之前的堆內(nèi)存示意圖:

從上圖可以看出堆內(nèi)存的分為新生代、老年代和永久代。新生代又被進(jìn)一步分為:Eden 區(qū)+Survior1 區(qū)+Survior2 區(qū)。值得注意的是,在JDK1.8中移除整個(gè)永久代,取而代之的是一個(gè)叫元空間(Metaspace)的區(qū)域(永久代使用的是JVM的堆內(nèi)存空間,而元空間使用的是物理內(nèi)存,直接受到本機(jī)的物理內(nèi)存限制)。

分代回收算法

目前主流的垃圾收集器都會(huì)采用分代回收算法,因此需要將堆內(nèi)存分為新生代和老年代,這樣我們就可以根據(jù)各個(gè)年代的特點(diǎn)選擇合適的垃圾收集算法。

大多數(shù)情況下,對(duì)象在新生代中 eden 區(qū)分配。當(dāng) eden 區(qū)沒有足夠空間進(jìn)行分配時(shí),虛擬機(jī)將發(fā)起一次Minor GC。

Minor Gc和Full GC 有什么不同呢?

新生代GC(Minor GC):指發(fā)生新生代的的垃圾收集動(dòng)作,Minor GC非常頻繁,回收速度一般也比較快。

老年代GC(Major GC/Full GC):指發(fā)生在老年代的GC,出現(xiàn)了Major GC經(jīng)常會(huì)伴隨至少一次的Minor GC(并非絕對(duì)),Major GC的速度一般會(huì)比Minor GC的慢10倍以上。

4.2 判斷對(duì)象是否死亡

堆中幾乎放著所有的對(duì)象實(shí)例,對(duì)堆垃圾回收前的第一步就是要判斷那些對(duì)象已經(jīng)死亡(即不能再被任何途徑使用的對(duì)象)。

4.2.1 引用計(jì)數(shù)法

給對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它,計(jì)數(shù)器就加1;當(dāng)引用失效,計(jì)數(shù)器就減1;任何時(shí)候計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的。

這個(gè)方法實(shí)現(xiàn)簡(jiǎn)單,效率高,但是目前主流的虛擬機(jī)中并沒有選擇這個(gè)算法來管理內(nèi)存,其最主要的原因是它很難解決對(duì)象之間相互循環(huán)引用的問題。

所謂對(duì)象之間的相互引用問題,如下面代碼所示:除了對(duì)象objA和objB相互引用著對(duì)方之外,這兩個(gè)對(duì)象之間再無任何引用。但是他們因?yàn)榛ハ嘁脤?duì)方,導(dǎo)致它們的引用計(jì)數(shù)器都不為0,于是引用計(jì)數(shù)算法無法通知 GC 回收器回收他們。

public class Test {
    Object instance = null;
    public static void main(String[] args) {
        Test objA = new Test();
        Test objB = new Test();
        objA.instance = objB;
        objB.instance = objA;
        objA = null;
        objB = null;
    }
}

4.2.2 可達(dá)性分析算法

這個(gè)算法的基本思想就是通過一系列的稱為 “GC Roots” 的對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)開始向下搜索,節(jié)點(diǎn)所走過的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到 GC Roots 沒有任何引用鏈相連的話,則證明此對(duì)象是不可用的。

4.2.3 再談引用

無論是通過引用計(jì)數(shù)法判斷對(duì)象引用數(shù)量,還是通過可達(dá)性分析法判斷對(duì)象的引用鏈?zhǔn)欠窨蛇_(dá),判定對(duì)象的存活都與“引用”有關(guān)。

JDK1.2以后,Java對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為強(qiáng)引用、軟引用、弱引用、虛引用四種(引用強(qiáng)度逐漸減弱)

關(guān)于四種引用以及源代碼分析,可以看我的這篇文章:https://blog.csdn.net/m0_3770...

4.3 不可達(dá)的對(duì)象并非“非死不可”

即使在可達(dá)性分析法中不可達(dá)的對(duì)象,也并非是“非死不可”的,這時(shí)候它們暫時(shí)處于“緩刑階段”,要真正宣告一個(gè)對(duì)象死亡,至少要經(jīng)歷兩次標(biāo)記過程;可達(dá)性分析法中不可達(dá)的對(duì)象被第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是此對(duì)象是否有必要執(zhí)行 finalize 方法。當(dāng)對(duì)象沒有覆蓋 finalize 方法,或 finalize 方法已經(jīng)被虛擬機(jī)調(diào)用過時(shí),虛擬機(jī)將這兩種情況視為沒有必要執(zhí)行。

被判定為需要執(zhí)行的對(duì)象將會(huì)被放在一個(gè)隊(duì)列中進(jìn)行第二次標(biāo)記,除非這個(gè)對(duì)象與引用鏈上的任何一個(gè)對(duì)象建立關(guān)聯(lián),否則就會(huì)被真的回收。

4.4 如何判斷一個(gè)常量是廢棄常量 4.5 如何判斷一個(gè)類是無用的類

方法區(qū)主要回收的是無用的類,那么如何判斷一個(gè)類是無用的類的呢?要判定一個(gè)類是否是“無用的類”的條件則相對(duì)苛刻許多。類需要同時(shí)滿足下面3個(gè)條件才能算是 “無用的類”

該類所有的實(shí)例都已經(jīng)被回收,也就是 Java 堆中不存在該類的任何實(shí)例。

加載該類的 ClassLoader 已經(jīng)被回收。

該類對(duì)應(yīng)的 java.lang.Class 對(duì)象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

虛擬機(jī)可以對(duì)滿足上述3個(gè)條件的無用類進(jìn)行回收,這里說的僅僅是“可以”,而并不是和對(duì)象一樣不使用了就會(huì)必然被回收。

4.6 GC回收算法詳解

這個(gè)可以看我的另外一篇文章:https://blog.csdn.net/m0_3770...

05.String類和常量池 5.1 String對(duì)象的兩種創(chuàng)建方式

1 String 對(duì)象的兩種創(chuàng)建方式:

String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false

這兩種不同的創(chuàng)建方法是有差別的【記?。褐灰褂胣ew方法,便需要?jiǎng)?chuàng)建新的對(duì)象】

第一種方式是在常量池中拿對(duì)象

第二種方式是直接在堆內(nèi)存空間創(chuàng)建一個(gè)新的對(duì)象。

5.2 String類型的常量池

String 類型的常量池比較特殊。它的主要使用方法有兩種:

直接使用雙引號(hào)聲明出來的 String 對(duì)象會(huì)直接存儲(chǔ)在常量池中。

如果不是用雙引號(hào)聲明的 String 對(duì)象,可以使用 String 提供的 intern 方String.intern() 是一個(gè) Native 方法,它的作用是:如果運(yùn)行時(shí)常量池中已經(jīng)包含一個(gè)等于此 String 對(duì)象內(nèi)容的字符串,則返回常量池中該字符串的引用;如果沒有,則在常量池中創(chuàng)建與此 String 內(nèi)容相同的字符串,并返回常量池中創(chuàng)建的字符串的引用。

String s1 = new String("yc");
String s2 = s1.intern();
String s3 = "yc";
System.out.println(s2);//yc
System.out.println(s1 == s2);//false,因?yàn)橐粋€(gè)是堆內(nèi)存中的String對(duì)象一個(gè)是常量池中的String對(duì)象,
System.out.println(s3 == s2);//true,因?yàn)閮蓚€(gè)都是常量池中的String對(duì)
關(guān)于其他內(nèi)容介紹 01.關(guān)于博客匯總鏈接

1.技術(shù)博客匯總

2.開源項(xiàng)目匯總

3.生活博客匯總

4.喜馬拉雅音頻匯總

5.其他匯總

02.關(guān)于我的博客

我的個(gè)人站點(diǎn):www.yczbj.org,www.ycbjie.cn

github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/...

簡(jiǎn)書:http://www.jianshu.com/u/b7b2...

csdn:http://my.csdn.net/m0_37700275

喜馬拉雅聽書:http://www.ximalaya.com/zhubo...

開源中國(guó):https://my.oschina.net/zbj161...

泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...

郵箱:[email protected]

阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV

segmentfault頭條:https://segmentfault.com/u/xi...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71994.html

相關(guān)文章

  • Java類加載機(jī)制

    摘要:當(dāng)前類加載器和所有父類加載器都無法加載該類時(shí),拋出異常。加載兩份相同的對(duì)象的情況和不屬于父子類加載器關(guān)系,并且各自都加載了同一個(gè)類。類加載機(jī)制與接口當(dāng)虛擬機(jī)初始化一個(gè)類時(shí),不會(huì)初始化該類實(shí)現(xiàn)的接口。 類加載機(jī)制 概念 類加載器把class文件中的二進(jìn)制數(shù)據(jù)讀入到內(nèi)存中,存放在方法區(qū),然后在堆區(qū)創(chuàng)建一個(gè)java.lang.Class對(duì)象,用來封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)。 1、加載: 查...

    aaron 評(píng)論0 收藏0
  • 反射機(jī)制與原理筆記

    反射機(jī)制與原理筆記 聲明 文章均為本人技術(shù)筆記,轉(zhuǎn)載請(qǐng)注明出處https://segmentfault.com/u/yzwall 反射機(jī)制 反射:當(dāng)程序無法獲知對(duì)象類型時(shí),在運(yùn)行期間動(dòng)態(tài)獲取類的所有屬性和方法,這種動(dòng)態(tài)獲取類信息和動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為反射機(jī)制;反射機(jī)制實(shí)現(xiàn):Class類與java.lang.reflect類庫(kù)一起實(shí)現(xiàn)機(jī)制,java.lang.reflect類庫(kù)包含F(xiàn)ield...

    fobnn 評(píng)論0 收藏0
  • 詳細(xì)深入分析 Java ClassLoader 工作機(jī)制

    摘要:作用負(fù)責(zé)將加載到中審查每個(gè)類由誰加載父優(yōu)先的等級(jí)加載機(jī)制將字節(jié)碼重新解析成統(tǒng)一要求的對(duì)象格式類結(jié)構(gòu)分析為了更好的理解類的加載機(jī)制,我們來深入研究一下和他的方法。就算兩個(gè)是同一份字節(jié)碼,如果被兩個(gè)不同的實(shí)例所加載,也會(huì)認(rèn)為它們是兩個(gè)不同。 申明:本文首發(fā)于 詳細(xì)深入分析 ClassLoader 工作機(jī)制 ,如有轉(zhuǎn)載,注明原出處即可,謝謝配合。 什么是 ClassLoader ? 大家...

    mdluo 評(píng)論0 收藏0
  • jvm類加載機(jī)制

    摘要:前面提到,對(duì)于數(shù)組類來說,它并沒有對(duì)應(yīng)的字節(jié)流,而是由虛擬機(jī)直接生成的。對(duì)于其他的類來說,虛擬機(jī)則需要借助類加載器來完成查找字節(jié)流的過程。驗(yàn)證階段的目的,在于確保被加載類能夠滿足虛擬機(jī)的約束條件。 Java 虛擬機(jī)將字節(jié)流轉(zhuǎn)化為 Java 類的過程。這個(gè)過程可分為加載、鏈接以及初始化 三大步驟。 加載是指查找字節(jié)流,并且據(jù)此創(chuàng)建類的過程。加載需要借助類加載器,在 Java 虛擬機(jī)中,類...

    lastSeries 評(píng)論0 收藏0
  • Java的類加載機(jī)制

    摘要:如果需要支持類的動(dòng)態(tài)加載或需要對(duì)編譯后的字節(jié)碼文件進(jìn)行解密操作等,就需要與類加載器打交道了。雙親委派模型,雙親委派模型,約定類加載器的加載機(jī)制。任何之類的字節(jié)碼都無法調(diào)用方法,因?yàn)樵摲椒ㄖ荒茉陬惣虞d的過程中由調(diào)用。 jvm系列 垃圾回收基礎(chǔ) JVM的編譯策略 GC的三大基礎(chǔ)算法 GC的三大高級(jí)算法 GC策略的評(píng)價(jià)指標(biāo) JVM信息查看 GC通用日志解讀 jvm的card table數(shù)據(jù)...

    aervon 評(píng)論0 收藏0
  • 從一無所知到無所不知————jvm系列(1)

    摘要:學(xué)習(xí)能更深入的理解這門語言,能理解語言底層的執(zhí)行過程,深入到字節(jié)碼層次。 目錄 ? 前言 程序的運(yùn)行 1.JVM類加載機(jī)制 ①一般在什么情況下會(huì)去加載一個(gè)類?也就是說,什么時(shí)候.class字節(jié)碼文件中加載這個(gè)類到JVM內(nèi)存里來? ②驗(yàn)證、準(zhǔn)備、初始化 ③初始化 2.類加載器和雙親委派機(jī)制 ...

    Betta 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

mikyou

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<