這篇文章主要介紹了Java虛擬機(jī)問(wèn)題有哪些,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
創(chuàng)新互聯(lián)致力于成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè),成都網(wǎng)站設(shè)計(jì),集團(tuán)網(wǎng)站建設(shè)等服務(wù)標(biāo)準(zhǔn)化,推過(guò)標(biāo)準(zhǔn)化降低中小企業(yè)的建站的成本,并持續(xù)提升建站的定制化服務(wù)水平進(jìn)行質(zhì)量交付,讓企業(yè)網(wǎng)站從市場(chǎng)競(jìng)爭(zhēng)中脫穎而出。 選擇創(chuàng)新互聯(lián),就選擇了安全、穩(wěn)定、美觀的網(wǎng)站建設(shè)服務(wù)!運(yùn)行時(shí)數(shù)據(jù)區(qū)域有哪些?
它是方法區(qū)的一部分。Class文件中除了有關(guān)的版本、字段、方法、接口等描述信息外、還有一項(xiàng)信息是常量池,用于存放編輯期生成的各種字面量和符號(hào)引用,這部分內(nèi)容將在類(lèi)加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放
Java語(yǔ)言并不要求常量一定只有編輯期才能產(chǎn)生,也就是可能將新的常量放入池中,這種特性被開(kāi)發(fā)人員利用得比較多的便是String類(lèi)的intern()方法
當(dāng)常量池?zé)o法再申請(qǐng)到內(nèi)存時(shí)會(huì)拋出OutOfMemoryError異常
方法區(qū)它用于儲(chǔ)存已被虛擬機(jī)加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)
除了Java堆一樣不需要連續(xù)的內(nèi)存和可以選擇固定大小或者可擴(kuò)展外,還可以選擇不實(shí)現(xiàn)垃圾收集。這個(gè)區(qū)域的內(nèi)存回收目標(biāo)主要是針對(duì)常量池的回收和對(duì)類(lèi)型的卸載
當(dāng)方法區(qū)無(wú)法滿(mǎn)足內(nèi)存分配需求時(shí),將拋出OutOfMemoryErroy異常
堆是Java虛擬機(jī)所管理的內(nèi)存中大的一塊。Java堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)的時(shí)候創(chuàng)建,此內(nèi)存區(qū)域的唯一目的是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里分配內(nèi)存。所有的對(duì)象實(shí)例和數(shù)組都在堆上分配
Java堆是垃圾收集器管理的主要區(qū)域。Java堆細(xì)分為新生代和老年代
不管怎樣,劃分的目的都是為了更好的回收內(nèi)存,或者更快地分配內(nèi)存
Java堆可以處于物理上不連續(xù)的內(nèi)存空間中,只要邏輯上是連續(xù)的即可。如果在堆中沒(méi)有完成實(shí)例分配,并且堆也無(wú)法在擴(kuò)展時(shí)將會(huì)拋出OutOfMemoryError異常
本地方法棧和虛擬機(jī)棧發(fā)揮的作用是非常類(lèi)似的,他們的區(qū)別是虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機(jī)使用到的Native方法服務(wù)
本地方法棧區(qū)域也會(huì)拋出StackOverflowError和OutOfMemoryErroy異常
虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀用于儲(chǔ)存局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。每個(gè)方法從調(diào)用直至完成的過(guò)程,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過(guò)程。
技術(shù)博客大總結(jié)
棧內(nèi)存就是虛擬機(jī)棧,或者說(shuō)是虛擬機(jī)棧中局部變量表的部分
局部變量表存放了編輯期可知的各種基本數(shù)據(jù)類(lèi)型(boolean、byte、char、short、int、float、long、double)、對(duì)象引用(refrence)類(lèi)型和returnAddress類(lèi)型(指向了一條字節(jié)碼指令的地址)
其中64位長(zhǎng)度的long和double類(lèi)型的數(shù)據(jù)會(huì)占用兩個(gè)局部變量空間,其余的數(shù)據(jù)類(lèi)型只占用1個(gè)。
Java虛擬機(jī)規(guī)范對(duì)這個(gè)區(qū)域規(guī)定了兩種異常狀況:如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度,將拋出StackOverflowError異常。如果虛擬機(jī)擴(kuò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存,就會(huì)跑出OutOfMemoryError異常
程序計(jì)數(shù)器是一塊較小的內(nèi)存,他可以看做是當(dāng)前線程所執(zhí)行的行號(hào)指示器。字節(jié)碼解釋器工作的時(shí)候就是通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼的指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴(lài)這個(gè)計(jì)數(shù)器來(lái)完成。如果線程正在執(zhí)行的是一個(gè)Java方法,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是Native方法,這個(gè)計(jì)數(shù)器則為空。此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒(méi)有規(guī)定任何OutOfMemotyError情況的區(qū)域
Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機(jī)棧、本地方法棧、堆、程序計(jì)數(shù)器,其中方法區(qū)和堆是由線程共享的數(shù)據(jù)區(qū),其他幾個(gè)是線程隔離的數(shù)據(jù)區(qū)
1.1 程序計(jì)數(shù)器
1.2 Java虛擬機(jī)棧
1.3 本地方法棧
1.4 Java堆
1.5 方法區(qū)
1.6 運(yùn)行時(shí)常量池
對(duì)象的內(nèi)存布局?
a) 儲(chǔ)存對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼、GC分帶年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID、偏向時(shí)間戳
b) 另一部分是指類(lèi)型指針,即對(duì)象指向它的類(lèi)元數(shù)據(jù)的指針,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是那個(gè)類(lèi)的實(shí)例
在HotSpot虛擬機(jī)中,對(duì)象在內(nèi)存中儲(chǔ)存的布局可以分為3塊區(qū)域:對(duì)象頭、實(shí)例數(shù)據(jù)和對(duì)齊填充
對(duì)象頭包括兩部分:
對(duì)象的訪問(wèn)定位方式有哪些?
Java堆對(duì)象的布局就必須考慮如何訪問(wèn)類(lèi)型數(shù)據(jù)的相關(guān)信息,而refreence中存儲(chǔ)的直接就是對(duì)象的地址
Java堆中將會(huì)劃分出一塊內(nèi)存來(lái)作為句柄池,reference中存儲(chǔ)的就是對(duì)象的句柄地址,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)與類(lèi)型數(shù)據(jù)各自的具體地址
使用句柄訪問(wèn)
使用直接指針訪問(wèn)
使用指針訪問(wèn)和使用句柄訪問(wèn)各具有何優(yōu)勢(shì)?
使用句柄訪問(wèn)優(yōu)勢(shì):reference中存儲(chǔ)的是穩(wěn)點(diǎn)的句柄地址,在對(duì)象被移動(dòng)(垃圾收集時(shí)移動(dòng)對(duì)象是非常普遍的行為)時(shí)只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針,而reference本身不需要修改
使用直接指針訪問(wèn)優(yōu)勢(shì):速度更快,節(jié)省了一次指針定位的時(shí)間開(kāi)銷(xiāo),由于對(duì)象的訪問(wèn)在Java中非常頻繁,因此這類(lèi)開(kāi)銷(xiāo)積少成多后也是一項(xiàng)非??捎^的執(zhí)行成本
技術(shù)博客大總結(jié)
說(shuō)一下對(duì)象的創(chuàng)建過(guò)程?比如:Dog dog= new Dog();
當(dāng)虛擬機(jī)執(zhí)行到new指令時(shí),它先在常量池中查找“Dog”,看能否定位到Dog類(lèi)的符號(hào)引用;如果能,說(shuō)明這個(gè)類(lèi)已經(jīng)被加載到方法區(qū)了,則繼續(xù)執(zhí)行。如果沒(méi)有,就讓Class Loader先執(zhí)行類(lèi)的加載。
然后,虛擬機(jī)開(kāi)始為該對(duì)象分配內(nèi)存,對(duì)象所需要的內(nèi)存大小在類(lèi)加載完成后就已經(jīng)確定了。這時(shí)候只要在堆中按需求分配空間即可。具體分配內(nèi)存時(shí)有兩種方式,第一種,內(nèi)存絕對(duì)規(guī)整,那么只要在被占用內(nèi)存和空閑內(nèi)存間放置指針即可,每次分配空間時(shí)只要把指針向空閑內(nèi)存空間移動(dòng)相應(yīng)距離即可,當(dāng)某對(duì)象被GC回收后,則需要進(jìn)行某些對(duì)象內(nèi)存的遷移。第二種,空閑內(nèi)存和非空閑內(nèi)存夾雜在一起,那么就需要用一個(gè)列表來(lái)記錄堆內(nèi)存的使用情況,然后按需分配內(nèi)存。
對(duì)于多線程的情況,如何確保一個(gè)線程分配了對(duì)象內(nèi)存但尚未修改內(nèi)存管理指針時(shí),其他線程又分配該塊內(nèi)存而覆蓋的情況?有一種方法,就是讓每一個(gè)線程在堆中先預(yù)分配一小塊內(nèi)存(TLAB本地線程分配緩沖),每個(gè)線程只在自己的內(nèi)存中分配內(nèi)存。但對(duì)象本身按其訪問(wèn)屬性是可以線程共享訪問(wèn)的。
內(nèi)存分配到后,虛擬機(jī)將分配的內(nèi)存空間都初始化為零值(不包括對(duì)象頭)。實(shí)例變量按變量類(lèi)型初始化相應(yīng)的默認(rèn)值(數(shù)值型為0,boolan為false),所以實(shí)例變量不賦初值也能使用。接著設(shè)置對(duì)象頭信息,比如對(duì)象的哈希值,GC分代年齡等。技術(shù)博客大總結(jié)
從虛擬機(jī)角度,此時(shí)一個(gè)新的對(duì)象已經(jīng)創(chuàng)建完成了。但從我們程序運(yùn)行的角度,新建對(duì)象才剛剛開(kāi)始,對(duì)象的構(gòu)造方法還沒(méi)有執(zhí)行。只有執(zhí)行完構(gòu)造方法,按構(gòu)造方法進(jìn)行初始化后,對(duì)象才是徹底創(chuàng)建完成了。構(gòu)造函數(shù)的執(zhí)行還涉及到調(diào)用父類(lèi)構(gòu)造器,如果沒(méi)有顯式聲明調(diào)用父類(lèi)構(gòu)造器,則自動(dòng)添加默認(rèn)構(gòu)造器。
new運(yùn)算符可以返回堆中這個(gè)對(duì)象的引用
變量創(chuàng)建過(guò)程種放在虛擬機(jī)哪里?
如果dog局部變量,dog變量在棧幀的局部變量表,這個(gè)對(duì)象的引用就放在棧幀。
如果dog是實(shí)例變量,dog變量在堆中,對(duì)象的引用就放在堆。
如果dog是靜態(tài)變量,dog變量在方法區(qū),對(duì)象的引用就放在方法區(qū)。
變量是實(shí)例變量、局部變量或靜態(tài)變量的不同將引用放在不同的地方:
OutOfMemoryError異常在哪些數(shù)據(jù)區(qū)域中可能會(huì)出現(xiàn)?
Java堆溢出
虛擬機(jī)棧和本地方法棧溢出
方法區(qū)和運(yùn)行時(shí)常量池溢出
分別說(shuō)一下這個(gè)數(shù)據(jù)區(qū)域出現(xiàn)OOM的場(chǎng)景和緣由?
String.intern()是一個(gè)Native方法,它的作用是:如果字符串常量池中已經(jīng)包含一個(gè)等于此String對(duì)象的字符串,則返回代表池中這個(gè)字符串的String對(duì)象;否則,將此String對(duì)象包含的字符串添加到常量池中,并且返回此String對(duì)象的引用
由于常量池分配在永久代中,可以通過(guò)-XX:PermSize和-XX:MaxPermSize限制方法區(qū)大小,從而間接限制其中常量池的容量。技術(shù)博客大總結(jié)
Intern():JDK1.6 intern方法會(huì)把首次遇到的字符串實(shí)例復(fù)制到永久代,返回的也是永久代中這個(gè)字符串實(shí)例的引用,而由StringBuilder創(chuàng)建的字符串實(shí)例在Java堆上,所以必然不是一個(gè)引用。JDK1.7 intern()方法的實(shí)現(xiàn)不會(huì)再?gòu)?fù)制實(shí)例,只是在常量池中記錄首次出現(xiàn)的實(shí)例引用,因此intern()返回的引用和由StringBuilder創(chuàng)建的那個(gè)字符串實(shí)例是同一個(gè)
對(duì)于HotSpot來(lái)說(shuō),雖然-Xoss參數(shù)(設(shè)置本地方法棧大?。┐嬖?,但實(shí)際上是無(wú)效的,棧容量只由-Xss參數(shù)設(shè)定。關(guān)于虛擬機(jī)棧和本地方法棧,在Java虛擬機(jī)規(guī)范中描述了兩種異常:
如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的大深度,將拋出StackOverflowError
如果虛擬機(jī)在擴(kuò)展棧時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常
在單線程下,無(wú)論由于棧幀太大還是虛擬機(jī)棧容量太小,當(dāng)內(nèi)存無(wú)法分配的時(shí)候,虛擬機(jī)拋出的都是StackOverflowError異常
如果是多線程導(dǎo)致的內(nèi)存溢出,與??臻g是否足夠大并不存在任何聯(lián)系,這個(gè)時(shí)候每個(gè)線程的棧分配的內(nèi)存越大,反而越容易產(chǎn)生內(nèi)存溢出異常。解決的時(shí)候是在不能減少線程數(shù)或更換64為的虛擬機(jī)的情況下,就只能通過(guò)減少大堆和減少棧容量來(lái)?yè)Q取更多的線程
Java堆用于存儲(chǔ)對(duì)象實(shí)例,只要不斷的創(chuàng)建對(duì)象,并且保證GCRoots到對(duì)象之間有可達(dá)路徑來(lái)避免垃圾回收機(jī)制清除這些對(duì)象,那么在數(shù)量到達(dá)大堆的容量限制后就會(huì)產(chǎn)生內(nèi)存溢出異常
如果是內(nèi)存泄漏,可進(jìn)一步通過(guò)工具查看泄漏對(duì)象到GC Roots的引用鏈。于是就能找到泄露對(duì)象是通過(guò)怎樣的路徑與GC Roots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無(wú)法自動(dòng)回收它們的。掌握了泄漏對(duì)象的類(lèi)型信息及GC Roots引用鏈的信息,就可以比較準(zhǔn)確地定位出泄漏代碼的位置
如果不存在泄露,換句話(huà)說(shuō),就是內(nèi)存中的對(duì)象確實(shí)都還必須存活著,那就應(yīng)當(dāng)檢查虛擬機(jī)的堆參數(shù)(-Xmx與-Xms),與機(jī)器物理內(nèi)存對(duì)比看是否還可以調(diào)大,從代碼上檢查是否存在某些對(duì)象生命周期過(guò)長(zhǎng)、持有狀態(tài)時(shí)間過(guò)長(zhǎng)的情況,嘗試減少程序運(yùn)行期的內(nèi)存消耗
Java堆溢出
虛擬機(jī)棧和本地方法棧溢出
方法區(qū)和運(yùn)行時(shí)常量池溢出
Java中堆和棧的區(qū)別?
棧內(nèi)存:主要用來(lái)存放基本數(shù)據(jù)類(lèi)型和局部變量;當(dāng)在代碼塊定義一個(gè)變量時(shí)會(huì)在棧中為這個(gè)變量分配內(nèi)存空間,當(dāng)超過(guò)變量的作用域后這塊空間就會(huì)被自動(dòng)釋放掉。
堆內(nèi)存:用來(lái)存放運(yùn)行時(shí)創(chuàng)建的對(duì)象,比如通過(guò)new關(guān)鍵字創(chuàng)建出來(lái)的對(duì)象和數(shù)組;需要由Java虛擬機(jī)的自動(dòng)垃圾回收器來(lái)管理。
分別寫(xiě)出堆內(nèi)存溢出與棧內(nèi)存溢出的程序?
棧內(nèi)存溢出
public void A() { A(); }
堆內(nèi)存溢出
public void testd() { Listlist = new ArrayList<>(); int i = 0; while (true) { list.add(new String(i + "")); i++; } }
如果對(duì)象的引用被置為null,垃圾收集器是否會(huì)立即釋放對(duì)象占用的內(nèi)存?
不會(huì),在下一個(gè)垃圾回收周期中,這個(gè)對(duì)象將是可被回收的。
也就是說(shuō)當(dāng)一個(gè)對(duì)象的引用變?yōu)閚ull時(shí),并不會(huì)被垃圾收集器立刻回收,而是在下一次垃圾回收時(shí)才會(huì)釋放其占用的內(nèi)存。
java中垃圾收集的方法有哪些
現(xiàn)在的虛擬機(jī)垃圾收集大多采用這種方式,它根據(jù)對(duì)象的生存周期,將堆分為新生代和老年代。在新生代中,由于對(duì)象生存期短,每次回收都會(huì)有大量對(duì)象死去,那么這時(shí)就采用復(fù)制算法。老年代里的對(duì)象存活率較高,沒(méi)有額外的空間進(jìn)行分配擔(dān)保,所以可以使用標(biāo)記-整理 或者 標(biāo)記-清除。
該算法主要是為了解決標(biāo)記-清除,產(chǎn)生大量?jī)?nèi)存碎片的問(wèn)題;當(dāng)對(duì)象存活率較高時(shí),也解決了復(fù)制算法的效率問(wèn)題。它的不同之處就是在清除對(duì)象的時(shí)候現(xiàn)將可回收對(duì)象移動(dòng)到一端,然后清除掉端邊界以外的對(duì)象,這樣就不會(huì)產(chǎn)生內(nèi)存碎片了。
為了解決效率問(wèn)題,復(fù)制算法將可用內(nèi)存按容量劃分為相等的兩部分,然后每次只使用其中的一塊,當(dāng)一塊內(nèi)存用完時(shí),就將還存活的對(duì)象復(fù)制到第二塊內(nèi)存上,然后一次性清楚完第一塊內(nèi)存,再將第二塊上的對(duì)象復(fù)制到第一塊。但是這種方式,內(nèi)存的代價(jià)太高,每次基本上都要浪費(fèi)一般的內(nèi)存。
于是將該算法進(jìn)行了改進(jìn),內(nèi)存區(qū)域不再是按照1:1去劃分,而是將內(nèi)存劃分為8:1:1三部分,較大那份內(nèi)存交Eden區(qū),其余是兩塊較小的內(nèi)存區(qū)叫Survior區(qū)。每次都會(huì)優(yōu)先使用Eden區(qū),若Eden區(qū)滿(mǎn),就將對(duì)象復(fù)制到第二塊內(nèi)存區(qū)上,然后清除Eden區(qū),如果此時(shí)存活的對(duì)象太多,以至于Survivor不夠時(shí),會(huì)將這些對(duì)象通過(guò)分配擔(dān)保機(jī)制復(fù)制到老年代中。(java堆又分為新生代和老年代)
這是垃圾收集算法中最基礎(chǔ)的,根據(jù)名字就可以知道,它的思想就是標(biāo)記哪些要被回收的對(duì)象,然后統(tǒng)一回收。這種方法很簡(jiǎn)單,但是會(huì)有兩個(gè)主要問(wèn)題:1.效率不高,標(biāo)記和清除的效率都很低;2.會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,導(dǎo)致以后程序在分配較大的對(duì)象時(shí),由于沒(méi)有充足的連續(xù)內(nèi)存而提前觸發(fā)一次GC動(dòng)作。
標(biāo)記-清除:
復(fù)制算法:
標(biāo)記-整理技術(shù)博客大總結(jié)
分代收集
所謂引用計(jì)數(shù)法就是給每一個(gè)對(duì)象設(shè)置一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用這個(gè)對(duì)象時(shí),就將計(jì)數(shù)器加一,引用失效時(shí),計(jì)數(shù)器就減一。當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)器為零時(shí),說(shuō)明此對(duì)象沒(méi)有被引用,也就是“死對(duì)象”,將會(huì)被垃圾回收.
引用計(jì)數(shù)法有一個(gè)缺陷就是無(wú)法解決循環(huán)引用問(wèn)題,也就是說(shuō)當(dāng)對(duì)象A引用對(duì)象B,對(duì)象B又引用者對(duì)象A,那么此時(shí)A,B對(duì)象的引用計(jì)數(shù)器都不為零,也就造成無(wú)法完成垃圾回收,所以主流的虛擬機(jī)都沒(méi)有采用這種算法。
引用計(jì)數(shù)法
2.可達(dá)性算法(引用鏈法)
虛擬機(jī)棧中引用的對(duì)象
方法區(qū)類(lèi)靜態(tài)屬性引用的對(duì)象
方法區(qū)常量池引用的對(duì)象
本地方法棧JNI引用的對(duì)象
該算法的思想是:從一個(gè)被稱(chēng)為GC Roots的對(duì)象開(kāi)始向下搜索,如果一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí),則說(shuō)明此對(duì)象不可用。
在java中可以作為GC Roots的對(duì)象有以下幾種:
如何理解一個(gè)對(duì)象不一定會(huì)被回收?技術(shù)博客大總結(jié)
雖然這些算法可以判定一個(gè)對(duì)象是否能被回收,但是當(dāng)滿(mǎn)足上述條件時(shí),一個(gè)對(duì)象比不一定會(huì)被回收。當(dāng)一個(gè)對(duì)象不可達(dá)GC Root時(shí),這個(gè)對(duì)象并不會(huì)立馬被回收,而是出于一個(gè)死緩的階段,若要被真正的回收需要經(jīng)歷兩次標(biāo)記
如果對(duì)象在可達(dá)性分析中沒(méi)有與GCRoot的引用鏈,那么此時(shí)就會(huì)被第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是是否有必要執(zhí)行finalize()方法。當(dāng)對(duì)象沒(méi)有覆蓋finalize()方法或者已被虛擬機(jī)調(diào)用過(guò),那么就認(rèn)為是沒(méi)必要的。
如果該對(duì)象有必要執(zhí)行finalize()方法,那么這個(gè)對(duì)象將會(huì)放在一個(gè)稱(chēng)為F-Queue的對(duì)隊(duì)列中,虛擬機(jī)會(huì)觸發(fā)一個(gè)Finalize()線程去執(zhí)行,此線程是低優(yōu)先級(jí)的,并且虛擬機(jī)不會(huì)承諾一直等待它運(yùn)行完,這是因?yàn)槿绻鹒inalize()執(zhí)行緩慢或者發(fā)生了死鎖,那么就會(huì)造成F-Queue隊(duì)列一直等待,造成了內(nèi)存回收系統(tǒng)的崩潰。GC對(duì)處于F-Queue中的對(duì)象進(jìn)行第二次被標(biāo)記,這時(shí),該對(duì)象將被移除”即將回收”集合,等待回收。
Class.forName() 和ClassLoader.loadClass()區(qū)別?
問(wèn)到的是反射,但是在底層涉及到了虛擬機(jī)的類(lèi)加載知識(shí)。
Class.forName() 默認(rèn)執(zhí)行類(lèi)加載過(guò)程中的連接與初始化動(dòng)作,一旦執(zhí)行初始化動(dòng)作,靜態(tài)變量就會(huì)被初始化為程序員設(shè)置的值,如果有靜態(tài)代碼塊,靜態(tài)代碼塊也會(huì)被執(zhí)行
ClassLoader.loadClass() 默認(rèn)只執(zhí)行類(lèi)加載過(guò)程中的加載動(dòng)作,后面的動(dòng)作都不會(huì)執(zhí)行
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Java虛擬機(jī)問(wèn)題有哪些”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。