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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

《深入理解Java虚拟机》读书笔记

發(fā)布時間:2023/12/10 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《深入理解Java虚拟机》读书笔记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

堆分配參數(shù):

-XX:+PrintGC 使用該參數(shù),虛擬機啟動后,只要遇到GC就會打印日志;

-XX:+UseSerialGC 配置串行回收器;

-XX:+PrintGCDeltails 可以查看詳細信息,包括各個區(qū)的情況

-Xms:設置Java程序啟動時初始堆的大小(主要參數(shù))

-Xmx:設置Java程序能獲得的最大堆大小(主要參數(shù))

新生代的配置:

-Xmn: 可以設置新生代的大小,設置一個比較大的新生代會減少老年代的大小,這個設置對系統(tǒng)性能以及GC行為有很大的影響,新生代大小一般會設置整個堆空間的1/3到1/4左右。

備注:在實際工作中,可以直接將初始的堆大小與最大堆大小設置相等,這樣的好處是可以減少程序運行時的垃圾回收次數(shù),從而提高性能。

常見異常:

???????? java.lang.OutOfMemoryError.Java heap spacess---heap

?????????????????? JVM中如果98%的時間是用于GC且可用的Heap size不足2%的時候?qū)伋龃水惓P畔ⅰ?/p>

?????????????????? -Xms -Xmx

???????? java.lang.OutOfMemoryError.PermGen space ---no heap

?????????????????? -XX:PermSize

?????????????????? -XX:MaxPermSize

???????? StrackOverflowError

?????????????????? Java虛擬機在運行時,調(diào)用方法時,都需要創(chuàng)建棧幀,當棧的空間不夠時就會產(chǎn)生StrackOverflowError

??????????????????????????? -Xss

?

JVM中的參數(shù):

???????? 以-X開頭的都是非標準的(這些參數(shù)并不保證在所有的JVM上都被實現(xiàn))。

?????????????????? -Xmx

?????????????????? -Xmn

?????????????????? -Xms

???????? 以-XX開頭的都是不穩(wěn)定的并且不推薦在生產(chǎn)環(huán)境中使用,這些參數(shù)的改動也不會發(fā)布通知。

?????????????????? -XX:Permsize

?????????????????? -XX:MaxPermsize

??????????????????

JVM選項的說明:

???????? 布爾型參數(shù)選項:-XX+表示打開,-XX-表示關(guān)閉。(-XX.+PrintGCDetails)

???????? 數(shù)字型參數(shù)選項通過-XX=設定。

???????? 字符型參數(shù)選項通過-XX=設定,通常用來指定一個文件、路徑或者一個命令列表

???????? -Xms:初始堆大小

???????? -Xmx:最大堆大小

???????? -XX:NewSize=n 設置年輕代的大小

???????? -XX:NewRatio=n 設置年輕代和老年代的比值。如3則表示年輕代和老年代的比值為1:3

???????? -XX:SurvivorRatio=n 年輕代中Eden與兩個Survivor區(qū)的比值。如為3,則表示Eden:Survivor=3:2。一個Survivor占整個年輕代的1/5.

???????? -XX:MaxPermSize=n 設置永久代的大小

?

JVM GC

???????? 串行回收器(Serial Collector)

???????? 并行回收器(Parallel Collector)

???????? 并行合并回收器(Parallel Compacting Collection)

???????? 并發(fā)標記清除回收器(Concurrent Mark-Sweep Collector)應用廣泛

???????? G1垃圾收集器(Jdk7+)未來的主流

???????? 并行算法是用多線程進行垃圾回收,回收期間會暫停程序的執(zhí)行,而并發(fā)算法,也是多線程回收,但期間不停止應用執(zhí)行。所以,并發(fā)算法適用于交互性高的一些程序。經(jīng)過觀察,并發(fā)算法會減少年輕代的大小,其實就是使用了一個大的年老代,這反過來跟并行算法相比吞吐量相對較低。

????????

JVM垃圾回收時間:

???????? 當年輕代內(nèi)存滿時,會引發(fā)一次普通GC,該GC僅回收年輕代。需要強調(diào)的是,年輕代滿是指Eden代滿,Survivor滿不會引發(fā)GC

???????? 當老年代滿時會引發(fā)Full GC,Full GC將會同時回收年輕代、年老代

???????? 當永久代滿時也會引發(fā)Full GC,會導致Class、Method元信息的卸載

?

常見問題:

???????? ?Q:為什么崩潰前垃圾回收的時間越來越長?

?? A:根據(jù)內(nèi)存模型和垃圾回收算法,垃圾回收分兩部分:內(nèi)存標記、清除(復制),標記部分只要內(nèi)存大小固定時間是不變的,變的是復制部分,因為每次垃圾回收都有一些回收不掉的內(nèi)存,所以增加了復制量,導致時間延長。所以,垃圾回收的時間也可以作為判斷內(nèi)存泄漏的依據(jù)

?? Q:為什么Full GC的次數(shù)越來越多?

?? A:因為內(nèi)存的積累,逐漸耗盡了年老代的內(nèi)存,導致新對象分配沒有更多的空間,從而導致頻繁的垃圾回收

?? Q:為什么年老代占用的內(nèi)存越來越大?

?? A:因為年輕代的內(nèi)存無法被回收,越來越多地被Copy到年老代

?? Q:什么是串行回收和并行回收?

?? A:串行回收是指在同一時間段內(nèi)只允許一件事情發(fā)生,即當多個CPU可用時,也只能有一個CPU用于執(zhí)行垃圾回收操作,并且在執(zhí)行垃圾回收時,程序中的工作線程將會被暫停。當垃圾回收工作完成后才會恢復之前被暫停的工作線程,這就是串行回收。

?? 并行回收是指可以運用多個CPU同時執(zhí)行垃圾回收,因此提升了應用程序的吞吐量,不過并行垃圾回收仍然使用了“Stop-the-World”機制和復制算法。

?? Q:什么是并發(fā)和“Stop-the-World”機制?

?? 當通過“Stop-the-World”機制回收垃圾時,垃圾收集器會在內(nèi)存回收的過程中暫停程序中的所有工作線程,直至完成內(nèi)存回收工作后才會恢復之前被暫停的工作線程。

?? 并發(fā)回收是指在同一時間段內(nèi),應用程序的工作線程和垃圾回收線程將會同時運行或者交叉運行。

Q:什么是快速分配策略?

A:基于線程安全的考慮,如果一個類在分配內(nèi)存之前已經(jīng)成功完成裝載步驟之后,JVM就會優(yōu)先選擇在TLAB(Thread Local Allocation本地線程分配緩沖區(qū))中為對象實例分配內(nèi)存空間,TLAB在Java堆區(qū)中是一塊線程私有的區(qū)域,包含在Eden空間內(nèi),除了可以避免一系列的非線程安全問題外,同時還能夠提升內(nèi)存分配的吞吐量,因此我們可以將這種內(nèi)存分配方式稱之為快速分配策略。

Q:什么是逃逸分析和棧上分配?

A:Java堆區(qū)已經(jīng)不再是對象分配內(nèi)存的唯一選擇,如果希望降低GC的回收平率和提升GC的回收效率,那么則可以使用堆外存儲技術(shù),目前最常見的堆外存儲技術(shù)就是利用逃逸分析技術(shù)篩選出未發(fā)生逃逸的對象,然后避開堆區(qū)而直接選擇在棧幀中分配內(nèi)存空間。逃逸分析是JVM在執(zhí)行性能優(yōu)化之前的一種分析技術(shù),它的具體目標就是分析出對象的作用域。即當一個對象被定義在方法體內(nèi)部之后,它的受訪權(quán)限僅限于方法體內(nèi),一旦其引用被外部成員引用后,這個對象就發(fā)生了逃逸。反之如果定義在方法體內(nèi)部的對象并沒有被任何外部成員引用時,JVM就會為其在棧幀中分配內(nèi)存空間。

HeapOutOfMemory
當堆上分配的對象大于指定堆的最大值時,拋出該錯。
可以使用-XX:+HeapDumpOnOutOfMemoryError 查看內(nèi)存快照進行分析

MethodArea OutOfMemory
方法區(qū)內(nèi)存不足,存放類信息,常量,靜態(tài)變量,即時編譯后的代碼,檢查這幾個信息是否有異常 大多的原因是因為動態(tài)產(chǎn)生過多的類。

ConstantPool OutOfMemory
常量池溢出,查看是否intern使用不當

DirectMemory OutOfMemory
本機直接內(nèi)存溢出,容量可通過-XX:MaxDirectMemorySize指定,如果不指定,默認和堆最大值相同。這個溢出發(fā)生在系統(tǒng)進行直接內(nèi)存分配。例如:unsafe.allocateMemory()
特征為:OOM后發(fā)現(xiàn)Dump問價你很小,程序中直接或間接使用了NIO

?

Stack OutOfMemory
擴展棧時無法獲取足夠的內(nèi)存空間,在創(chuàng)建線程時
解決方法之一:減少最大堆

Stack OverFlow
棧深度大于虛擬機所允許的深度,經(jīng)常是由于死循環(huán)的遞歸調(diào)用

第三章:垃圾收集器和內(nèi)存分配策略

1、JVM垃圾回收區(qū)域:

程序計數(shù)器、虛擬機棧、本地方法棧三個區(qū)域隨線程而生,隨線程而滅;棧中的棧幀隨著方法的進入和退出而有條不紊的執(zhí)行著出棧和入棧操作。每一個棧幀中分配多少內(nèi)存基本是在類結(jié)構(gòu)確定下來時就已知的,因此這三個區(qū)域的內(nèi)存分配和回收都具有確定性,在這三個區(qū)域內(nèi)不需要過多考慮回收的問題,因為方法結(jié)束或者線程結(jié)束時,內(nèi)存自然就跟著回收了。而java堆和方法區(qū)不一樣,一個接口中的多個實現(xiàn)類需要的內(nèi)存可能不一樣,一個方法中的多個分支需要的內(nèi)存也不一樣,我們只有在程序運行時才能知道會創(chuàng)建哪些對象,這部分內(nèi)存的分配和回收是動態(tài)的,垃圾收集器所關(guān)注的是這部分內(nèi)存。

2、引用計數(shù)算法:

???????? 給對象中添加一個引用計數(shù)器,每當有一個地方引用它時,計數(shù)器值就加1;當引用失效計數(shù)器值就減1;任何時刻計數(shù)器都為0的對象就是不可能再被使用的。Java語言并沒有選用引用計數(shù)器算法來管理內(nèi)存,其中最主要的原因就是它很難解決對象之間相互循環(huán)引用的問題。

3、根搜索算法:

???????? Java使用根搜索算法(GC Root Tracing)判斷對象是否存活。該算法的基本思路是:通過一系列的名為“GC Root”的對象作為起始點,從這些節(jié)點開始向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用鏈相連(用圖論的話來說就是從GC Roots到這個對象不可達)時,則證明此對象是不可引用的,所以它們將會被判定為可回收對象。在Java語言中可作為GC Roots的對象包括下面幾種:

虛擬機棧(棧幀中的本地變量表)中的引用的對象;

???????? 方法區(qū)中的類靜態(tài)屬性引用的對象;

???????? 運行時常量池中的對象引用;

???????? 方法區(qū)中的常量引用的對象;

???????? 本地方法棧中JNI(即一般所說的native方法)引用的對象。

???????? 對象引用:無論是通過引用計數(shù)器算法判斷對象的引用數(shù)量,還是通過根搜索算法判斷對象的引用鏈是否可達,判斷對象是否存活都與“引用”有關(guān)。JDK1.2之后,Java將引用分為四種:強引用,軟引用,弱引用,虛引用。這四種引用強度依次逐漸減弱。

4、回收方法區(qū):

???????? 永久代(方法區(qū))的垃圾收集主要回收兩部分內(nèi)容:廢棄常量和無用的類。回收廢棄常量與回收Java堆中的對象非常相似。以常量池中的字面量的回收為例,假如一個字符串“abc”已經(jīng)進入了常量池中,但是當前系統(tǒng)沒有任何一個String對象叫做“abc”的,也沒有其他地方引用了這個字面量,如果這個時候發(fā)生內(nèi)存回收,而且必要的話,這個“abc”常量就會被系統(tǒng)“請”出常量池。常量池中的其他類(接口)、方法、字段的符號引用也與此類似。判斷一個類是否是“無用的類”需要滿足下面三個條件:

???????? 該類所有的實例都已經(jīng)被回收,即Java堆中不存在該類的任何實例;

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

???????? 該類對應的java.lang.Class對象沒有在任何對方被引用,無法在任何地方通過反射訪問該類的方法。

5、垃圾回收算法之標記-清除算法:

???????? 這是最基礎(chǔ)的收集算法。分為兩個階段,標記和清除。首先標記出所有需要回收的對象,在標記完成后統(tǒng)一回收掉所有被標記的對象。

???????? 缺點:效率低下;

???????? 空間問題,標記清除之后會產(chǎn)生大量不連續(xù)的內(nèi)存碎片。

6、垃圾回收算法之復制算法:

???????? 該算法將內(nèi)存按容量劃分為大小相等的兩塊區(qū)域,每次只使用其中的一塊。當一塊內(nèi)存用完了,就將其中還存活的對象復制到另一塊區(qū)域上,然后再將已經(jīng)使用過的內(nèi)存區(qū)域一次性清理掉。解決了內(nèi)存碎片的問題。

???????? 說明:現(xiàn)在的商業(yè)虛擬機都是采用這種收集算法來回收新生代,IBM的專門研究表明,新生代中的對象98%是朝生夕死的,所有并不需要按照1:1的比例來劃分內(nèi)存空間,而是將內(nèi)存劃分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中的一塊Survivor。當回收時候,將Eden和Survivor中還存活的對象一次性復制到另外一塊Survivor空間上,最后清理掉Eden和剛剛用過的Survivor的空間。HotSpot虛擬機默認Eden和Survivor的大小比例是8:1:1。

?????????????????? 缺點:在對象存活率較高時需要執(zhí)行較多的復制操作,效率將會變低,老年代不能使用這種算法。

7、垃圾回收算法之標記-整理算法:

???????? 根據(jù)老年代的特點,有人提出了“標記-整理”算法。其中標記過程和“標記-清除”算法一樣,但是后續(xù)步驟不是直接對可回收的對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內(nèi)存。

8、垃圾回收算法之分代收集算法:

???????? 當前商業(yè)虛擬機的垃圾回收都是采用“分代收集”算法,根據(jù)對象的存活周期的不同將內(nèi)存劃分為幾塊。一般是把Java堆分為新生代和老年代,這樣就可以根據(jù)各個年代的特點采用最適合的收集算法。在新生代中,每次垃圾收集時都會發(fā)現(xiàn)有大量對象死去,只有少量對象存活,那就選擇復制算法;而老年代中因為對象存活率較高,沒有額外空間對它進行分配擔保,就必須采用“標記-清除”或者“標記-整理”算法來進行回收。

9、垃圾收集器之Serial收集器:

???????? Serial收集器是最基本、歷史最悠久的收集器。該收集器是一個單線程的收集器,即在進行垃圾收集時候,必須暫停其他所有的工作線程,直到它收集結(jié)束。到目前為止,它依然是虛擬機運行在Client模式下的默認新生代收集器。優(yōu)點是簡單而高效。目前停頓時間可以控制在幾十毫秒最多一百多毫秒以內(nèi)。

10、垃圾收集器之G1收集器:

???????? G1(Garbage first)收集器是當前收集器技術(shù)發(fā)展的最前沿成果。G1收集器是垃圾收集器理論進一步發(fā)展的產(chǎn)物,它與CMS收集器相比有兩個顯著的改進:一是G1收集器是基于“標記-整理”算法實現(xiàn)的收集器;二是它可以非常精準地控制停頓,既能讓使用者明確指定在一個長度為M毫秒的時間片段內(nèi),消耗在垃圾收集上的時間不得超過N毫秒。

???????? G1收集器可以實現(xiàn)在基本不犧牲吞吐量的前提下完成低停頓的內(nèi)存回收,這是由于它能夠極力的避免全區(qū)域的垃圾收集,G1收集器將整個Java堆(包括新生代、老年代)劃分為多個大小固定的獨立區(qū)域(Region),并且跟蹤這些區(qū)域里面的垃圾堆積程度,在后臺維護一個優(yōu)先列表,每次根據(jù)允許的收集時間,優(yōu)先回收垃圾最多的區(qū)域(這就是G1名稱的由來)。

垃圾收集器比較

垃圾收集器

算法

方式

堆區(qū)域

機制

Serial收集器

復制算法

串行

新生代

Stop-the-World

Serial Old收集器

標記-壓縮算法

串行

老年代

Stop-the-World

ParNew收集器

復制算法

并行

新生代

Stop-the-World

Parallel收集器

復制算法

并行

新生代

Stop-the-World

Parallel Old收集

標記-壓縮算法

并行

老年代

Stop-the-World

CMS收集器

標記-清除算法

并行

老年代

Stop-the-World/并發(fā)

G1收集器

?

?

整個堆區(qū)

?

?

內(nèi)存選項配置

選項

描述

備注

-Xms

設置Java堆區(qū)的初始內(nèi)存

當可用的Java堆區(qū)內(nèi)存小于40%時,JVM就會將內(nèi)存調(diào)整到選項-Xmx所允許的最大值

-Xmx

設置Java堆區(qū)的最大內(nèi)存

當可用的Java堆區(qū)內(nèi)存大于70%時,JVM就會將內(nèi)存調(diào)整到選項-Xms所指定的初始值

-Xmn

設置新生代(YoungGen)的內(nèi)存

-Xmn的內(nèi)存大小為Eden+2個Surivivor空間的值,官方建議配置為整個堆的3/8

-XX:NewSize

設置新生代(YoungGen)的初始內(nèi)存

和選項-Xmn等價,但是推薦使用-Xmn,相當于一次性設定了NewSize/Max-NewSize的內(nèi)存大小

-XX:MaxNewSize

設置新生代(YoungGen)的最大內(nèi)存

?

-XX:NewRatio

新生代(Eden+2個Surivivor空間)與老年代的比值,不包括永久代

選項-XX:NewRatio=4時,表示新生代與老年代所占的比值為1:4。如果已經(jīng)設置了選項-Xmn,則無需設置該選項

-XX:PermSize

設置方法區(qū)的初始內(nèi)存

?

-XX:MaxPermSize

設置方法區(qū)的最大內(nèi)存

?

-XX:SurivivorRatio

Eden空間與2個Surivivor空間的比值大小

Eden空間和另外2個Surivivor空間缺省所占的比值為8:1

-XX:TLABWasteTargetPercent

設置TLAB空間所占用Eden空間的百分比大小

?

?

GC組合配置

GC組合

Minor GC

Full GC

描述

-XX:+UserSerialGC

Serial收集器串行回收

Serial Old收集器串行回收

選項-XX:UseSerialGC

可以手動指定使用Serial收集器+Serial Old收集器組合執(zhí)行內(nèi)存回收

-XX:+UseParNewGC

ParNew收集器并行回收

Serial Old收集器串行回收

選項-XX:UseParNewGC可以手動指定使用ParNew收集器+Seral Old收集器組合執(zhí)行內(nèi)存回收

-XX:+UseParallelGC

Parallel收集器并行回收

Serial Old收集器串行回收

通過-XX:+UseParallelGC可以手動指定使用Parallel收集器和Serial Old收集器組合執(zhí)行內(nèi)存回收

-XX:+UseParallelOldGC

Parallel收集器并行回收

Parallel Old收集器并行回收

通過-XX:+UseParallelOldGC可以手動指定使用Parallel收集器和Parallel Old收集器組合執(zhí)行內(nèi)存回收

-XX:+UseConcMarkSweepGC

ParNew收集器并行回收

缺省使用CMS收集器并發(fā)執(zhí)行回收,備用采用Serial Old收集器串行回收

使用-XX:+UseConcMarkSweepGC可以手動指定使用ParNew收集器+CMS收集器+Serial Old收集器組合執(zhí)行內(nèi)存回收。優(yōu)先使用ParNew+CMS組合,當出現(xiàn)ConcurrentNode Failure或者Promotion Failed時,則采用ParNew+Serial Old組合。

-XX:+UseConcMarkSweepGC

-XX:+UseParNewGC

Serial 收集器串行回收

-XX:+UseG1GC

G1收集器并發(fā)、并行的內(nèi)存回收

?

?

第七章:虛擬機類加載機制

1、虛擬機的類加載機制:

虛擬機把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存中,并對數(shù)據(jù)進行校驗、轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制。

2、類被加載到虛擬機經(jīng)過的7個階段:

類從被加載到虛擬機內(nèi)存中開始,到卸載出內(nèi)存為止,它的整個生命周期包括了:加載、校驗、準備、解析、初始化、使用和卸載七個階段。其中校驗/驗證、準備和解析三個部分統(tǒng)稱為連接。

3、何時進行類的初始化?

虛擬機規(guī)范嚴格規(guī)定了有且只有四種情況必須立即對類進行初始化(而加載、校驗、準備和解析自然需要在初始化之前開始):

1)遇到new、getstatic、putstatic、或者這4條字節(jié)碼指令時,invokestatic如果類沒有進行初始化,則需要先觸發(fā)其初始化,生成這4條指令最常見的Java代碼場景是:使用new關(guān)鍵字實例化對象的時候、讀取或者設置一個類的靜態(tài)字段(被final修飾、已經(jīng)在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時候,以及調(diào)用一個類的靜態(tài)方法的時候;

2)使用java.lang.reflect包的方法對類進行反射調(diào)用的時候,如果類沒有進行過初始化,則需要先觸發(fā)其初始化;

3)當初始化一個子類的時候,如果發(fā)現(xiàn)其父類還沒有進行過初始化,則需要先觸發(fā)其父類的初始化;

4)當虛擬機啟動時,用戶需要指定一個要執(zhí)行的主類(包含main方法的那個類),虛擬機會先初始化這個主類。

對于靜態(tài)字段,只有直接定義這個字段的類才會被初始化,因此通過其子類來引用父類中定義的靜態(tài)字段,只會觸發(fā)其父類的初始化而不會觸發(fā)子類的初始化。

4、加載:

在加載階段,虛擬機需要完成以下三件事情:

通過一個類的全限定名來獲取定義此類的二進制字節(jié)流;

將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu);

在Java堆中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口。

加載階段完成后,虛擬機外部的二進制字節(jié)流就按照虛擬機所需的格式存儲在方法區(qū)之中。然后在java堆中實例化一個java.lang.Class對象,這個對象將作為程序訪問方法區(qū)中的這些類型數(shù)據(jù)的外部接口,加載階段和連接階段的部分內(nèi)容(如一部分字節(jié)碼文件格式驗證動作)是交叉進行的,加載階段尚未完成,連接階段可能已經(jīng)開始,但是這些夾在加載階段之中的動作,仍然屬于連接階段的內(nèi)容,這兩個階段的開始時間仍然保持著固定的先后順序。

5、驗證:

驗證是連接階段的第一步,這一階段的目的是為了確保Class文件的字節(jié)流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全。

虛擬機驗證過程的四個階段:

文件格式驗證;

元數(shù)據(jù)驗證;

字節(jié)碼驗證;

符號引用驗證。

6、準備:

準備階段是正式為類變量分配內(nèi)存并設置類變量初始值的階段,這些內(nèi)存都將在方法區(qū)中進行分配。這個階段中有兩個容易產(chǎn)生混淆的概念,首先是這時候進行內(nèi)存分配的僅包含類變量(被static修飾的變量),而不包含實例變量,實例變量將會在對象實例化時隨著對象一起分配在Java堆中。其次是這里所說的初始值“通常情況”下是數(shù)據(jù)類型的零值,假設一個類變量的定義為:public static int value=123;那么變量value在準備階段過后的初始值為0,而不是123。

7、解析:

解析階段是虛擬機將常量池內(nèi)的符號引用替換成直接引用的過程。

符號引用:符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義的定位到目標即可。符號引用與虛擬機實現(xiàn)的內(nèi)存布局無關(guān)。引用的目標并不一定已經(jīng)加載到內(nèi)存中。

直接引用:直接引用可以是直接指向目標的指針、相對偏移量或者是一個能間接定位到目標的句柄。直接引用是與虛擬機實現(xiàn)的內(nèi)存布局相關(guān)的,同一符號引用在不同虛擬機實例上翻譯出來的直接引用一般不會相同。

7、類與類加載器:

虛擬機設計團隊把類加載階段中的“通過一個類的全限定名來獲取此類的二進制字節(jié)流”這個動作放到Java虛擬機外部去實現(xiàn),以便讓應用程序自己決定如何去獲取所修要的類。實現(xiàn)這個動作的代碼模塊被稱為“類加載器”。

類加載器雖然只用于實現(xiàn)類的加載動作,但它在Java程序中起到的作用卻遠遠不限于類加載階段。對于任意一個類,都需要由加載它的類加載器和這個類本身一同確定其在Java虛擬機中的唯一性。

8、雙親委派模型:

絕大部分Java程序都會使用到以下三種系統(tǒng)提供的類加載器:

1)啟動類加載器(BootStrap ClassLoader):在HotSpot虛擬機中這個類加載器由C++語言實現(xiàn),是虛擬機自身的一部分。它負責將存放在<JAVA_HOME>\lib目錄中的,并且是虛擬機標識的(僅按照文件名識別,如rt.jar,名稱不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內(nèi)存中。啟動類加載器無法被Java程序直接引用。

2)擴展類加載器(Extention ClassLoader):這個加載器有sun.misc.Launcher$ExtClassLoader實現(xiàn)。它負責加載<JAVA_HOME>/lib/ext目錄中的,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫,開發(fā)者可以直接使用擴展類加載器。

3)應用程序類加載器(Application ClassLoader):這個類加載器由sun.misc.Launcher$AppClassLoader來實現(xiàn)。由于這個類加載器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也稱它為系統(tǒng)類加載器。它負責加載用戶類路徑(ClassPath)上所指定的類庫。如果應用程序沒有指定自定義的類加載器,一般情況下這個就是程序中默認的類加載器。

我們的應用程序都是由這三個類加載器互相配合進行加載的。

雙親委派模型的工作過程:如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委托給父類加載器去完成。每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳遞到頂層的啟動類加載器中,只有當父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需加載的類)時,子加載器才會自己嘗試去加載。

????????

當一個Java程序響應很慢時如何查找問題

?

轉(zhuǎn)載于:https://www.cnblogs.com/wrong5566/p/6531832.html

總結(jié)

以上是生活随笔為你收集整理的《深入理解Java虚拟机》读书笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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