日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

JVM入门

發(fā)布時(shí)間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM入门 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 什么是JVM
    • 內(nèi)存結(jié)構(gòu)
    • 垃圾回收
    • 類加載與字節(jié)碼技術(shù)

什么是JVM

定義

Java Virtual Machine,JAVA程序的運(yùn)行環(huán)境(JAVA二進(jìn)制字節(jié)碼的運(yùn)行環(huán)境)

好處

一次編寫,到處運(yùn)行
自動(dòng)內(nèi)存管理,垃圾回收機(jī)制
數(shù)組下標(biāo)越界檢查

內(nèi)存結(jié)構(gòu)


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

用于保存JVM中下一條所要執(zhí)行的指令的地址

特點(diǎn)

線程私有
CPU會(huì)為每個(gè)線程分配時(shí)間片,當(dāng)當(dāng)前線程的時(shí)間片使用完以后,CPU就會(huì)去執(zhí)行另一個(gè)線程中的代碼
程序計(jì)數(shù)器是每個(gè)線程所私有的,當(dāng)另一個(gè)線程的時(shí)間片用完,又返回來執(zhí)行當(dāng)前線程的代碼時(shí),通過程序計(jì)數(shù)器可以知道應(yīng)該執(zhí)行哪一句指令,不會(huì)存在內(nèi)存溢出

2、虛擬機(jī)棧

每個(gè)線程運(yùn)行需要的內(nèi)存空間,稱為虛擬機(jī)棧
每個(gè)棧由多個(gè)棧幀組成,對(duì)應(yīng)著每次調(diào)用方法時(shí)所占用的內(nèi)存
每個(gè)線程只能有一個(gè)活動(dòng)棧幀,對(duì)應(yīng)著當(dāng)前正在執(zhí)行的方法

問題辨析

垃圾回收是否涉及棧內(nèi)存?

不需要。因?yàn)樘摂M機(jī)棧中是由一個(gè)個(gè)棧幀組成的,在方法執(zhí)行完畢后,對(duì)應(yīng)的棧幀就會(huì)被彈出棧。所以無(wú)需通過垃圾回收機(jī)制去回收內(nèi)存。

棧內(nèi)存的分配越大越好嗎?

不是。因?yàn)槲锢韮?nèi)存是一定的,棧內(nèi)存越大,可以支持更多的遞歸調(diào)用,但是可執(zhí)行的線程數(shù)就會(huì)越少。

方法內(nèi)的局部變量是否是線程安全的?

如果方法內(nèi)局部變量沒有逃離方法的作用范圍,則是線程安全的
如果如果局部變量引用了對(duì)象,并逃離了方法的作用范圍,則需要考慮線程安全問題

內(nèi)存溢出

Java.lang.stackOverflowError 棧內(nèi)存溢出

發(fā)生原因

虛擬機(jī)棧中,棧幀過多(無(wú)限遞歸)
每個(gè)棧幀所占用過大
線程運(yùn)行診斷
CPU占用過高

3、本地方法棧

一些帶有native關(guān)鍵字的方法就是需要JAVA去調(diào)用本地的C或者C++方法,因?yàn)镴AVA有時(shí)候沒法直接和操作系統(tǒng)底層交互,所以需要用到本地方法

4、堆

通過new關(guān)鍵字創(chuàng)建的對(duì)象都會(huì)被放在堆內(nèi)存

特點(diǎn)

所有線程共享,堆內(nèi)存中的對(duì)象都需要考慮線程安全問題
有垃圾回收機(jī)制
堆內(nèi)存溢出
java.lang.OutofMemoryError :java heap space. 堆內(nèi)存溢出

堆內(nèi)存診斷

jps
jmap
jconsole
jvirsalvm

5、方法區(qū)

內(nèi)存溢出

1.8以前會(huì)導(dǎo)致永久代內(nèi)存溢出
1.8以后會(huì)導(dǎo)致元空間內(nèi)存溢出

常量池

二進(jìn)制字節(jié)碼的組成:類的基本信息、常量池、類的方法定義(包含了虛擬機(jī)指令)

常量池

就是一張表(如上圖中的constant pool),虛擬機(jī)指令根據(jù)這張常量表找到要執(zhí)行的類名、方法名、參數(shù)類型、字面量信息

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

常量池是.class文件中的,當(dāng)該類被加載以后,它的常量池信息就會(huì)放入運(yùn)行時(shí)常量池,并把里面的符號(hào)地址變?yōu)檎鎸?shí)地址

串池StringTable

常量池中的字符串僅是符號(hào),只有在被用到時(shí)才會(huì)轉(zhuǎn)化為對(duì)象
利用串池的機(jī)制,來避免重復(fù)創(chuàng)建字符串對(duì)象
字符串變量拼接的原理是StringBuilder
字符串常量拼接的原理是編譯器優(yōu)化
可以使用intern方法,主動(dòng)將串池中還沒有的字符串對(duì)象放入串池中
注意:無(wú)論是串池還是堆里面的字符串,都是對(duì)象



Jdk1.8


Jdk1.6

Jdk1.8 串池(StringTable)從方法區(qū)(永久代)移到堆中
Jdk1.6 運(yùn)行時(shí)常量池(永久代)字符串常量池(永久代)
Jdk1.8 運(yùn)行時(shí)常量池(元空間)串池(堆)

6、直接內(nèi)存

屬于操作系統(tǒng),常見于NIO操作時(shí),用于數(shù)據(jù)緩沖區(qū)
分配回收成本較高,但讀寫性能高
不受JVM內(nèi)存回收管理

文件讀寫流程

使用了DirectBuffer

直接內(nèi)存是操作系統(tǒng)和Java代碼都可以訪問的一塊區(qū)域,無(wú)需將代碼從系統(tǒng)內(nèi)存復(fù)制到Java堆內(nèi)存,從而提高了效率

垃圾回收

1、如何判斷對(duì)象可以回收

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

弊端:循環(huán)引用時(shí),兩個(gè)對(duì)象的計(jì)數(shù)都為1,導(dǎo)致兩個(gè)對(duì)象都無(wú)法被釋放

可達(dá)性分析算法

JVM中的垃圾回收器通過可達(dá)性分析來探索所有存活的對(duì)象
掃描堆中的對(duì)象,看能否沿著GC Root對(duì)象為起點(diǎn)的引用鏈找到該對(duì)象,如果找不到,則表示可以回收
可以作為GC Root的對(duì)象
虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象。 
方法區(qū)中類靜態(tài)屬性引用的對(duì)象
方法區(qū)中常量引用的對(duì)象
本地方法棧中JNI(即一般說的Native方法)引用的對(duì)象

五種引用

強(qiáng)引用
只有GC Root都不引用該對(duì)象時(shí),才會(huì)回收強(qiáng)引用對(duì)象

軟引用
當(dāng)GC Root指向軟引用對(duì)象時(shí),在內(nèi)存不足時(shí),會(huì)回收軟引用所引用的對(duì)象
如果在垃圾回收時(shí)發(fā)現(xiàn)內(nèi)存不足,在回收軟引用所指向的對(duì)象時(shí),軟引用本身不會(huì)被清理
如果想要清理軟引用,需要使用引用隊(duì)列
大概思路為:查看引用隊(duì)列中有無(wú)軟引用,如果有,則將該軟引用從存放它的集合中移除(這里為一個(gè)list集合)

弱引用
只有弱引用引用該對(duì)象時(shí),在垃圾回收時(shí),無(wú)論內(nèi)存是否充足,都會(huì)回收弱引用所引用的對(duì)象

虛引用

軟引用和弱引用可以配合引用隊(duì)列

在弱引用和虛引用所引用的對(duì)象被回收以后,會(huì)將這些引用放入引用隊(duì)列中,方便一起回收這些軟/弱引用對(duì)象
虛引用和終結(jié)器引用必須配合引用隊(duì)列

虛引用和終結(jié)器引用在使用時(shí)會(huì)關(guān)聯(lián)一個(gè)引用隊(duì)列

2、垃圾回收算法

標(biāo)記-清除

定義:標(biāo)記清除算法顧名思義,是指在虛擬機(jī)執(zhí)行垃圾回收的過程中,先采用標(biāo)記算法確定可回收對(duì)象,然后垃圾收集器根據(jù)標(biāo)識(shí)清除相應(yīng)的內(nèi)容,給堆內(nèi)存騰出相應(yīng)的空間

這里的騰出內(nèi)存空間并不是將內(nèi)存空間的字節(jié)清0,而是記錄下這段內(nèi)存的起始結(jié)束地址,下次分配內(nèi)存的時(shí)候,會(huì)直接覆蓋這段內(nèi)存
缺點(diǎn):容易產(chǎn)生大量的內(nèi)存碎片,可能無(wú)法滿足大對(duì)象的內(nèi)存分配,一旦導(dǎo)致無(wú)法分配對(duì)象,那就會(huì)導(dǎo)致jvm啟動(dòng)gc,一旦啟動(dòng)gc,我們的應(yīng)用程序就會(huì)暫停,這就導(dǎo)致應(yīng)用的響應(yīng)速度變慢

標(biāo)記-整理

標(biāo)記-整理 會(huì)將不被GC Root引用的對(duì)象回收,清楚其占用的內(nèi)存空間。然后整理剩余的對(duì)象,可以有效避免因內(nèi)存碎片而導(dǎo)致的問題,但是因?yàn)檎w需要消耗一定的時(shí)間,所以效率較低

復(fù)制

將內(nèi)存分為等大小的兩個(gè)區(qū)域,FROM和TO(TO中為空)。先將被GC Root引用的對(duì)象從FROM放入TO中,再回收不被GC Root引用的對(duì)象。然后交換FROM和TO。這樣也可以避免內(nèi)存碎片的問題,但是會(huì)占用雙倍的內(nèi)存空間

3、分代回收

回收流程

新創(chuàng)建的對(duì)象都被放在了新生代的伊甸園中
當(dāng)伊甸園中的內(nèi)存不足時(shí),就會(huì)進(jìn)行一次垃圾回收,這時(shí)的回收叫做 Minor GC
Minor GC 會(huì)將伊甸園和幸存區(qū)FROM存活的對(duì)象先復(fù)制到 幸存區(qū) TO中, 并讓其壽命加1,再交換兩個(gè)幸存區(qū)

再次創(chuàng)建對(duì)象,若新生代的伊甸園又滿了,則會(huì)再次觸發(fā) Minor GC(會(huì)觸發(fā) stop the world, 暫停其他用戶線程,只讓垃圾回收線程工作),這時(shí)不僅會(huì)回收伊甸園中的垃圾,還會(huì)回收幸存區(qū)中的垃圾,再將活躍對(duì)象復(fù)制到幸存區(qū)TO中。回收以后會(huì)交換兩個(gè)幸存區(qū),并讓幸存區(qū)中的對(duì)象壽命加1

如果幸存區(qū)中的對(duì)象的壽命超過某個(gè)閾值(最大為15,4bit),就會(huì)被放入老年代中

如果新生代老年代中的內(nèi)存都滿了,就會(huì)先觸發(fā)Minor GC,再觸發(fā)Full GC,掃描新生代和老年代中所有不再使用的對(duì)象并回收

4、垃圾回收器

并行收集:指多條垃圾收集線程并行工作,但此時(shí)用戶線程仍處于等待狀態(tài)。

并發(fā)收集:指用戶線程與垃圾收集線程同時(shí)工作(不一定是并行的可能會(huì)交替執(zhí)行)。用戶程序在繼續(xù)運(yùn)行,而垃圾收集程序運(yùn)行在另一個(gè)CPU上

吞吐量:即CPU用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值(吞吐量 = 運(yùn)行用戶代碼時(shí)間 / ( 運(yùn)行用戶代碼時(shí)間 + 垃圾收集時(shí)間 )),也就是。例如:虛擬機(jī)共運(yùn)行100分鐘,垃圾收集器花掉1分鐘,那么吞吐量就是99%

4.1、串行

單線程
內(nèi)存較小,個(gè)人電腦(CPU核數(shù)較少)

安全點(diǎn):讓其他線程都在這個(gè)點(diǎn)停下來,以免垃圾回收時(shí)移動(dòng)對(duì)象地址,使得其他線程找不到被移動(dòng)的對(duì)象

因?yàn)槭谴械?#xff0c;所以只有一個(gè)垃圾回收線程。且在該線程執(zhí)行回收工作時(shí),其他線程進(jìn)入阻塞狀態(tài)

Serial 收集器

Serial收集器是最基本的、發(fā)展歷史最悠久的收集器
特點(diǎn):單線程、簡(jiǎn)單高效(與其他收集器的單線程相比),采用復(fù)制算法。對(duì)于限定單個(gè)CPU的環(huán)境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程手機(jī)效率。收集器進(jìn)行垃圾回收時(shí),必須暫停其他所有的工作線程,直到它結(jié)束(Stop The World)

ParNew 收集器

ParNew收集器其實(shí)就是Serial收集器的多線程版本
特點(diǎn):多線程、ParNew收集器默認(rèn)開啟的收集線程數(shù)與CPU的數(shù)量相同,在CPU非常多的環(huán)境中,可以使用-XX:ParallelGCThreads參數(shù)來限制垃圾收集的線程數(shù)。和Serial收集器一樣存在Stop The World問題

Serial Old 收集器

Serial Old是Serial收集器的老年代版本
特點(diǎn):同樣是單線程收集器,采用標(biāo)記-整理算法

4.2、吞吐量?jī)?yōu)先

多線程
堆內(nèi)存較大,多核CPU
單位時(shí)間內(nèi),STW(stop the world,停掉其他所有工作線程)時(shí)間最短
JDK1.8默認(rèn)使用的垃圾回收器

Parallel Scavenge 收集器

與吞吐量關(guān)系密切,故也稱為吞吐量?jī)?yōu)先收集器
特點(diǎn):屬于新生代收集器也是采用復(fù)制算法的收集器(用到了新生代的幸存區(qū)),又是并行的多線程收集器(與ParNew收集器類似)

Parallel Old 收集器

是Parallel Scavenge收集器的老年代版本
特點(diǎn):多線程,采用標(biāo)記-整理算法(老年代沒有幸存區(qū))

4.3、響應(yīng)時(shí)間優(yōu)先

多線程
堆內(nèi)存較大,多核CPU
盡可能讓單次STW時(shí)間變短(盡量不影響其他線程運(yùn)行)

CMS 收集器

Concurrent Mark Sweep,一種以獲取最短回收停頓時(shí)間為目標(biāo)的老年代收集器

特點(diǎn):

基于標(biāo)記-清除算法實(shí)現(xiàn)。并發(fā)收集、低停頓,但是會(huì)產(chǎn)生內(nèi)存碎片

應(yīng)用場(chǎng)景:

適用于注重服務(wù)的響應(yīng)速度,希望系統(tǒng)停頓時(shí)間最短,給用戶帶來更好的體驗(yàn)等場(chǎng)景下。如web程序、b/s服務(wù)

CMS收集器的運(yùn)行過程分為下列4步:

初始標(biāo)記:標(biāo)記GC Roots能直接到的對(duì)象。速度很快但是仍存在Stop The World問題
并發(fā)標(biāo)記:進(jìn)行GC Roots Tracing 的過程,找出存活對(duì)象且用戶線程可并發(fā)執(zhí)行
重新標(biāo)記:為了修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄。仍然存在Stop The World問題
并發(fā)清除:對(duì)標(biāo)記的對(duì)象進(jìn)行清除回收

CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)執(zhí)行的

G1收集器

(JDK 9以后默認(rèn)使用,而且替代了CMS 收集器)

新生代伊甸園垃圾回收—–>內(nèi)存不足,新生代回收+并發(fā)標(biāo)記—–>回收新生代伊甸園、幸存區(qū)、老年代內(nèi)存——>新生代伊甸園垃圾回收(重新開始)

適用場(chǎng)景

同時(shí)注重吞吐量和低延遲(響應(yīng)時(shí)間)
超大堆內(nèi)存(內(nèi)存大的),會(huì)將堆內(nèi)存劃分為多個(gè)大小相等的區(qū)域
整體上是標(biāo)記-整理算法,兩個(gè)區(qū)域之間是復(fù)制算法

Young Collection (會(huì)STW)
(分區(qū)算法region)

分代是按對(duì)象的生命周期劃分,分區(qū)則是將堆空間劃分連續(xù)幾個(gè)不同小區(qū)間,每一個(gè)小區(qū)間獨(dú)立回收,可以控制一次回收多少個(gè)小區(qū)間,方便控制 GC 產(chǎn)生的停頓時(shí)間


Young Collection + CM(并發(fā)標(biāo)記)

在 Young GC 時(shí)會(huì)對(duì) GC Root 進(jìn)行初始標(biāo)記
在老年代占用堆內(nèi)存的比例達(dá)到閾值時(shí),對(duì)進(jìn)行并發(fā)標(biāo)記(不會(huì)STW),閾值可以根據(jù)用戶來進(jìn)行設(shè)定

Mixed Collection

會(huì)對(duì)E S O 進(jìn)行全面的回收:
最終標(biāo)記
拷貝存活

因?yàn)橹付俗畲笸nD時(shí)間,如果對(duì)所有老年代都進(jìn)行回收,耗時(shí)可能過高。為了保證時(shí)間不超過設(shè)定的停頓時(shí)間,會(huì)回收最有價(jià)值的老年代(回收后,能夠得到更多內(nèi)存)

Full GC

G1在老年代內(nèi)存不足時(shí)(老年代所占內(nèi)存超過閾值)
如果垃圾產(chǎn)生速度慢于垃圾回收速度,不會(huì)觸發(fā)Full GC,還是并發(fā)地進(jìn)行清理
如果垃圾產(chǎn)生速度快于垃圾回收速度,便會(huì)觸發(fā)Full GC

Young Collection 跨代引用(老年代引用新生代)

卡表與Remembered Set
Remembered Set 存在于E中,用于保存新生代對(duì)象對(duì)應(yīng)的臟卡
臟卡:O被劃分為多個(gè)區(qū)域(一個(gè)區(qū)域512K),如果該區(qū)域引用了新生代對(duì)象,則該區(qū)域被稱為臟卡
在引用變更時(shí)通過post-write barried + dirty card queue
concurrent refinement threads 更新 Remembered Set


Remark

重新標(biāo)記階段
在垃圾回收時(shí),收集器處理對(duì)象的過程中
黑色:已被處理,需要保留的 灰色:正在處理中的 白色:還未處理的

但是在并發(fā)標(biāo)記過程中,有可能A被處理了以后未引用C,但該處理過程還未結(jié)束,在處理過程結(jié)束之前A引用了C,這時(shí)就會(huì)用到remark

過程如下
之前C未被引用,這時(shí)A引用了C,就會(huì)給C加一個(gè)寫屏障,寫屏障的指令會(huì)被執(zhí)行,將C放入一個(gè)隊(duì)列當(dāng)中,并將C變?yōu)?處理中 狀態(tài)
在并發(fā)標(biāo)記階段結(jié)束以后,重新標(biāo)記階段會(huì)STW,然后將放在該隊(duì)列中的對(duì)象重新處理,發(fā)現(xiàn)有強(qiáng)引用引用它,就會(huì)處理它

類加載與字節(jié)碼技術(shù)


類加載階段

加載,連接,初始化

加載

將類的字節(jié)碼載入方法區(qū)(1.8后為元空間,在本地內(nèi)存中)中,內(nèi)部采用 C++ 的 instanceKlass 描述 java 類,它的重要 ?eld 有:
_java_mirror 即 java 的類鏡像,例如對(duì) String 來說,它的鏡像類就是 String.class,作用是把 klass 暴露給 java 使用
_super 即父類
_?elds 即成員變量
_methods 即方法
_constants 即常量池
_class_loader 即類加載器
_vtable 虛方法表
_itable 接口方法

如果這個(gè)類還有父類沒有加載,先加載父類
加載和鏈接可能是交替運(yùn)行的

InstanceKlass和*.class(JAVA鏡像類)互相保存了對(duì)方的地址
類的對(duì)象在對(duì)象頭中保存了*.class的地址。讓對(duì)象可以通過其找到方法區(qū)中的instanceKlass,從而獲取類的各種信息

連接

驗(yàn)證
驗(yàn)證類是否符合 JVM規(guī)范,安全性檢查
準(zhǔn)備
為 static 變量分配空間,設(shè)置默認(rèn)值
static變量在JDK 7以前是存儲(chǔ)與instanceKlass末尾。但在JDK 7以后就存儲(chǔ)在_java_mirror末尾了
static變量在分配空間和賦值是在兩個(gè)階段完成的。分配空間在準(zhǔn)備階段完成,賦值在初始化階段完成
如果 static 變量是 ?nal 的基本類型,以及字符串常量,那么編譯階段值就確定了,賦值在準(zhǔn)備階段完成
如果 static 變量是 ?nal 的,但屬于引用類型,那么賦值也會(huì)在初始化階段完成
解析
將常量池中的符號(hào)引用解析為直接引用

初始化

初始化階段就是執(zhí)行類構(gòu)造器clinit()方法的過程,虛擬機(jī)會(huì)保證這個(gè)類的『構(gòu)造方法』的線程安全
clinit()方法是由編譯器自動(dòng)收集類中的所有類變量的賦值動(dòng)作和靜態(tài)語(yǔ)句塊(static{}塊)中的語(yǔ)句合并產(chǎn)生的
注意
編譯器收集的順序是由語(yǔ)句在源文件中出現(xiàn)的順序決定的,靜態(tài)語(yǔ)句塊中只能訪問到定義在靜態(tài)語(yǔ)句塊之前的變量,定義在它之后的變量,在前面的靜態(tài)語(yǔ)句塊可以賦值,但是不能訪問,如

發(fā)生時(shí)機(jī)

—類的初始化的懶惰的,以下情況會(huì)初始化

main 方法所在的類,總會(huì)被首先初始化
首次訪問這個(gè)類的靜態(tài)變量或靜態(tài)方法時(shí)
子類初始化,如果父類還沒初始化,會(huì)引發(fā)
子類訪問父類的靜態(tài)變量,只會(huì)觸發(fā)父類的初始化
Class.forName
new 會(huì)導(dǎo)致初始化

—以下情況不會(huì)初始化

訪問類的 static ?nal 靜態(tài)常量(基本類型和字符串)
類對(duì)象.class 不會(huì)觸發(fā)初始化
創(chuàng)建該類對(duì)象的數(shù)組
類加載器的.loadClass方法
Class.forNamed的參數(shù)2為false時(shí)
驗(yàn)證類是否被初始化,可以看改類的靜態(tài)代碼塊是否被執(zhí)行

類加載器

Java虛擬機(jī)設(shè)計(jì)團(tuán)隊(duì)有意把類加載階段中的“通過一個(gè)類的全限定名來獲取描述該類的二進(jìn)制字節(jié)流”這個(gè)動(dòng)作放到Java虛擬機(jī)外部去實(shí)現(xiàn),以便讓應(yīng)用程序自己決定如何去獲取所需的類。實(shí)現(xiàn)這個(gè)動(dòng)作的代碼被稱為“類加載器”(ClassLoader)

類與類加載器

類加載器雖然只用于實(shí)現(xiàn)類的加載動(dòng)作,但它在Java程序中起到的作用卻遠(yuǎn)超類加載階段

對(duì)于任意一個(gè)類,都必須由加載它的類加載器和這個(gè)類本身一起共同確立其在Java虛擬機(jī)中的唯一性,每一個(gè)類加載器,都擁有一個(gè)獨(dú)立的類名稱空間。這句話可以表達(dá)得更通俗一些:比較兩個(gè)類是否“相等”,只有在這兩個(gè)類是由同一個(gè)類加載器加載的前提下才有意義,否則,即使這兩個(gè)類來源于同一個(gè)Class文件,被同一個(gè)Java虛擬機(jī)加載,只要加載它們的類加載器不同,那這兩個(gè)類就必定不相等


啟動(dòng)類加載器

可通過在控制臺(tái)輸入指令,使得類被啟動(dòng)類加器加載

拓展類加載器

如果classpath和JAVA_HOME/jre/lib/ext 下有同名類,加載時(shí)會(huì)使用拓展類加載器加載。當(dāng)應(yīng)用程序類加載器發(fā)現(xiàn)拓展類加載器已將該同名類加載過了,則不會(huì)再次加載

雙親委派模式

雙親委派模式,即調(diào)用類加載器ClassLoader 的 loadClass 方法時(shí),查找類的規(guī)則

首先查找該類是否已經(jīng)被該類加載器加載過了
如果沒有被加載過
看是否被它的上級(jí)加載器加載過了,如果沒有
看是否被啟動(dòng)類加載器加載過
如果還是沒有找到,先讓拓展類加載器調(diào)用findClass方法去找到該類,如果還是沒找到,就拋出異常
然后讓應(yīng)用類加載器去找classpath下找該類

總結(jié)

以上是生活随笔為你收集整理的JVM入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。