国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運營 > JAVA虛擬機(JVM)

JAVA虛擬機(JVM)

時間:2023-06-29 07:45:02 | 來源:網(wǎng)站運營

時間:2023-06-29 07:45:02 來源:網(wǎng)站運營

JAVA虛擬機(JVM):

一、JVM簡介

JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用于計算設(shè)備的規(guī)范,它是一個虛構(gòu)出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的。Java語言的一個非常重要的特點就是與平臺的無關(guān)性。而使用Java虛擬機是實現(xiàn)這一特點的關(guān)鍵。一般的高級語言如果要在不同的平臺上運行,至少需要編譯成不同的目標(biāo)代碼。而引入Java語言虛擬機后,Java語言在不同平臺上運行時不需要重新編譯。Java語言使用Java虛擬機屏蔽了與具體平臺相關(guān)的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺上不加修改地運行。Java虛擬機在執(zhí)行字節(jié)碼時,把字節(jié)碼解釋成具體平臺上的機器指令執(zhí)行。這就是Java的能夠“一次編譯,到處運行”的原因。


二、JVM的生命周期

JVM實例對應(yīng)了一個獨立運行的java程序,它是進(jìn)程級別。

1. 啟動:啟動一個Java程序時,一個JVM實例就產(chǎn)生了,任何一個擁有public static void main(String[] args)函數(shù)的class都可以作為JVM實例運行的起點。

2. 運行:main()作為該程序初始線程的起點,任何其他線程均由該線程啟動。

3. 消亡:當(dāng)程序中的所有非守護(hù)線程都終止時,JVM才退出,若安全管理器允許,程序也可以使用Runtime類或者System.exit()來退出。




JVM執(zhí)行引擎實例則對應(yīng)了屬于用戶運行程序的線程,它是線程級別。




Java的線程分為兩種:User Thread(用戶線程)、DaemonThread(守護(hù)線程)。

只要當(dāng)前JVM實例中尚存任何一個非守護(hù)(用戶)線程沒有結(jié)束,守護(hù)線程就全部工作;只有當(dāng)最后一個非守護(hù)線程結(jié)束是,守護(hù)線程隨著JVM一同結(jié)束工作,Daemon作用是為其他線程提供便利服務(wù),守護(hù)線程最典型的應(yīng)用就是GC(垃圾回收器),他就是一個很稱職的守護(hù)者。

守護(hù)線程與用戶線程的唯一區(qū)別是:其實User Thread線程和Daemon Thread守護(hù)線程本質(zhì)上來說去沒啥區(qū)別的,唯一的區(qū)別之處就在虛擬機的離開,當(dāng)JVM中所有的線程都是守護(hù)線程的時候,JVM就可以退出了(如果User Thread全部撤離,那么Daemon Thread也就沒什么線程好服務(wù)的了,所以虛擬機也就退出了);如果還有一個或以上的非守護(hù)線程則不會退出。(以上是針對正常退出,調(diào)用System.exit則必定會退出)。


三、JVM體系結(jié)構(gòu)

1. 類裝載器(ClassLoader)(用來裝載.class文件)。

2. 執(zhí)行引擎(執(zhí)行字節(jié)碼,或者執(zhí)行本地方法)。

3. 運行時數(shù)據(jù)區(qū)(方法區(qū)、堆、Java棧、PC寄存器、本地方法棧)。

JVM內(nèi)存結(jié)構(gòu)
JVM內(nèi)存結(jié)構(gòu),主要包括兩個子系統(tǒng)和兩個組件——

兩個子系統(tǒng)分別是Classloader子系統(tǒng)和Executionengine(執(zhí)行引擎)子系統(tǒng)。

兩個組件分別是RuntimeDataArea(運行時數(shù)據(jù)區(qū)域)組件和Nativeinterface(本地接口)組件。

1. Classloader子系統(tǒng)的作用——根據(jù)給定的全限定名類名(如java.lang.Object)來裝載class文件的內(nèi)容到Runtimedataarea中的methodarea(方法區(qū)域)。Java程序員可以extendsjava.lang.ClassLoader類來寫自己的Classloader。

2. Executionengine子系統(tǒng)的作用——執(zhí)行classes中的指令。任何JVMspecification實現(xiàn)(JVM)的核心都是Executionengine,不同的JDK,例如Sun的JDK和IBM的JDK好壞主要就取決于他們各自實現(xiàn)的Executionengine的好壞。

3. Nativeinterface組件——與nativelibraries交互,是其它編程語言交互的接口。當(dāng)調(diào)用native方法的時候,就進(jìn)入了一個全新的并且不再受虛擬機限制的世界,所以也很容易出現(xiàn)JVM無法控制的nativeheapOutOfMemory。

4. RuntimeDataArea組件(主要分為五個部分):Heap(堆)、MethodArea(方法區(qū)域)、JavaStack(Java的棧)、ProgramCounter(程序計數(shù)器)、Nativemethodstack(本地方法棧)。


四、JVM運行時的數(shù)據(jù)區(qū)

JVM運行時的數(shù)據(jù)區(qū)
1. Heap(Java堆)——

被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機啟動時創(chuàng)建;

用來存儲對象實例;

可以通過-Xmx和-Xms控制堆的大小。

OutOfMemoryError異常:當(dāng)在堆中沒有內(nèi)存完成實例分配,且堆也無法再擴展。




Java堆是垃圾收集器管理的主要區(qū)域。Java堆還可以細(xì)分為:新生代(New/Young)、舊生代/年老代(Old/Tenured)。持久代(Permanent)在方法區(qū),不屬于Heap。

Java堆的細(xì)分,新生代:舊生代=1:2、Eden : from : to = 8 : 1 : 1
新生代:新建的對象都由新生代分配內(nèi)存。常常又被劃分為Eden區(qū)和Survivor區(qū)。Eden空間不足時會把存活的對象轉(zhuǎn)移到Survivor。

新生代的大小可由-Xmn控制,也可用-XX:SurvivorRatio控制Eden和Survivor的比例。

舊生代:存放經(jīng)過多次垃圾回收仍然存活的對象。

持久代:存放靜態(tài)文件,如今Java類、方法等。持久代在方法區(qū),對垃圾回收沒有顯著影響。




2. 方法區(qū)——

線程間共享;

用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)

據(jù)。

OutOfMemoryError異常:當(dāng)方法區(qū)無法滿足內(nèi)存的分配需求時。




運行時常量池——

方法區(qū)的一部分;

用于存放編譯期生成的各種字面量與符號引用。

OutOfMemoryError異常:當(dāng)常量池?zé)o法再申請到內(nèi)存時。




3. Java虛擬機棧(VMStack)——

線程私有,生命周期與線程相同;

存儲方法的局部變量表(基本類型、對象引用)、操作數(shù)棧、動態(tài)鏈接、方法出口等

信息;

Java方法執(zhí)行的內(nèi)存模型,每個方法執(zhí)行的同時都會創(chuàng)建一個棧幀,每一個方法被調(diào)

用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機棧中從入棧到出棧的過程。

StackOverflowError異常:當(dāng)線程請求的棧深度大于虛擬機所允許的深度。

OutOfMemoryError異常:如果棧的擴展時無法申請到足夠的內(nèi)存。




JVM棧是線程私有的,每個線程創(chuàng)建的同時都會創(chuàng)建JVM棧,JVM棧中存放的為當(dāng)前線程中局部基本類型的變量、部分的返回結(jié)果以及Stack Frame。其他引用類型的對象在JVM棧上僅存放變量名和指向堆上對象實例的首地址。




4. 本地方法棧(NativeMethodStack)——

與虛擬機棧相似,主要為虛擬機使用到的Native方法服務(wù),在HotSpot虛擬機中直接

把本地方法棧與虛擬機棧二合一。




5. 程序計數(shù)器(Program Counter Register)——

當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器;

當(dāng)前線程私有;

不會出現(xiàn)OutOfMemoryError情況。




6. 直接內(nèi)存(Direct Memory)——

直接內(nèi)存并不是虛擬機運行的一部分,也不是Java虛擬機規(guī)范中定義的內(nèi)存區(qū)域,但

是這部分內(nèi)存也被頻繁使用;

NIO可以使用Native函數(shù)庫直接分配堆外內(nèi)存,堆中的DirectByteBuffer對象作為這

塊內(nèi)存的引用進(jìn)行操作;

大小不受Java堆大小的限制,受本機(服務(wù)器)內(nèi)存限制。

OutOfMemoryError異常:系統(tǒng)內(nèi)存不足時。




7. 總結(jié)——

Java對象實例存放在堆中;常量存放在方法區(qū)的常量池;虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)放在方法區(qū);以上區(qū)域是所有線程共享的。棧是線程私有的,存放該方法的局部變量表(基本類型、對象引用)、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。

一個Java程序?qū)?yīng)一個JVM,一個方法(線程)對應(yīng)一個Java棧。


五、Java代碼的編譯和執(zhí)行過程

1. Java代碼的編譯和執(zhí)行包括了三個重要機制——

Java源碼編譯機制(.java源代碼文件 -> .class字節(jié)碼文件);

類加載機制(ClassLoader);

類執(zhí)行機制(JVM執(zhí)行引擎)。




2. Java源碼編譯機制——

Java源代碼是不能被機器識別的,需要先經(jīng)過編譯器編譯成JVM可以執(zhí)行的.class字

節(jié)碼文件,再由解釋器解釋運行。即:Java源文件(.java)-- Java編譯器 --> Java字節(jié)

碼文件(.class)-- Java解釋器--> 執(zhí)行——

Java源碼編譯機制
字節(jié)碼文件(.class)是平臺無關(guān)的。

Java中字符只以一種形式存在:Unicode。字符轉(zhuǎn)換發(fā)生在JVM和OS交界處 (Reader/Writer)。

最后生成的class文件由以下部分組成——

結(jié)構(gòu)信息。包括class文件格式版本號及各部分的數(shù)量與大小的信息;

元數(shù)據(jù)。對應(yīng)于Java源碼中聲明與常量的信息。包含類/繼承的超類/實現(xiàn)的接口的聲

明信息、域與方法聲明信息和常量池;

方法信息。對應(yīng)Java源碼中語句和表達(dá)式對應(yīng)的信息。包含字節(jié)碼、異常處理器表、

求值棧與局部變量區(qū)大小、求值棧的類型記錄、調(diào)試符號信息。




3. 類加載機制(ClassLoader)——

Java程序并不一個可執(zhí)行文件,是由多個獨立的類文件組成。這些類文件并非一次性全部裝入內(nèi)存,而是依據(jù)程序逐步載入。JVM的類加載是通過ClassLoader及其子類來完成的,類的層次關(guān)系和加載順序——

類加載機制
(1)Bootstrap ClassLoader——

JVM的根ClassLoader,由C++實現(xiàn);

加載Java的核心API:$JAVA_HOME中jre/lib/rt.jar中所有class文件的加載,這個

jar中包含了java規(guī)范定義的所有接口以及實現(xiàn);

JVM啟動時即初始化此ClassLoader。

(2)Extension ClassLoader——

加載Java擴展API(lib/ext中的類)。

(3)App ClassLoader——

加載Classpath目錄下定義的class。

(4)Custom ClassLoader——

屬于應(yīng)用程序根據(jù)自身需要自定義的ClassLoader,如tomcat、jboss都會根據(jù)J2EE

規(guī)范自行實現(xiàn)ClassLoader。




雙親委派機制

JVM在加載類時默認(rèn)采用的是雙親委派機制。通俗的講,就是某個特定的類加載器在接到加載類的請求時,首先將加載任務(wù)委托給父類加載器,依次遞歸。如果父類加載器可以完成類加載任務(wù),就成功返回;只有父類加載器無法完成此加載任務(wù)時,才自己去加載。

作用:避免重復(fù)加載;更安全。如果不是雙親委派,那么用戶在自己的classpath編寫了一個java.lang.Object的類,那就無法保證Object的唯一性。所以使用雙親委派,即使自己編寫了,但是永遠(yuǎn)都不會被加載運行。




破壞雙親委派機制

雙親委派機制并不是一種強制性的約束模型,而是Java設(shè)計者推薦給開發(fā)者的類加載器實現(xiàn)方式。

線程上下文類加載器,這個類加載器可以通過java.lang.Thread類的setContextClassLoader()方法進(jìn)行設(shè)置,如果創(chuàng)建線程時還未設(shè)置,它將會從父線程中繼承一個,如果在應(yīng)用程序的全局范圍內(nèi)都沒有設(shè)置過的話,那么這個類加載器就是應(yīng)用程序類加載器。像JDBC就是采用了這種方式。這種行為就是逆向使用了加載器,違背了雙親委派模型的一般性原則。




4. 類執(zhí)行機制——

在執(zhí)行方法時JVM提供了四種指令來執(zhí)行:

(1)invokestatic:調(diào)用類的static方法;

(2)invokevirtual:調(diào)用對象實例的方法;

(3)invokeinterface:將屬性定義為接口來進(jìn)行調(diào)用;

(4)invokespecial:JVM對于初始化對象(Java構(gòu)造器的方法為:<init>)

以及調(diào)用對象實例中的私有方法時。




Java字節(jié)碼的執(zhí)行是由JVM執(zhí)行引擎來完成——

JVM執(zhí)行引擎
JVM是基于棧的體系結(jié)構(gòu)來執(zhí)行class字節(jié)碼的。線程創(chuàng)建后,都會產(chǎn)生程序計數(shù)器(PC)和棧(Stack),程序計數(shù)器存放下一條要執(zhí)行的指令在方法內(nèi)的偏移量,棧中存放一個個棧幀,每個棧幀對應(yīng)著每個方法的每次調(diào)用,而棧幀又是有局部變量區(qū)和操作數(shù)棧兩部分組成,局部變量區(qū)用于存放方法中的局部變量和參數(shù),操作數(shù)棧中用于存放方法執(zhí)行過程中產(chǎn)生的中間結(jié)果。




主要的執(zhí)行技術(shù)有:解釋,即時編譯,自適應(yīng)優(yōu)化、芯片級直接執(zhí)行(

解釋屬于第一代JVM,

即時編譯JIT屬于第二代JVM,

自適應(yīng)優(yōu)化,Sun的HotspotJVM采用這種技術(shù),吸取第一代JVM和第二代JVM的經(jīng)

驗,采用兩者結(jié)合的方式。),

開始對所有的代碼都采取解釋執(zhí)行的方式,并監(jiān)視代碼執(zhí)行情況,然后對那些經(jīng)常調(diào)用的方法啟動一個后臺線程,將其編譯為本地代碼,并進(jìn)行優(yōu)化。若方法不再頻繁使用,則取消編譯過的代碼,仍對其進(jìn)行解釋執(zhí)行。


六、JVM垃圾回收(GC)

1. GC的基本原理:將內(nèi)存中不再被引用的對象進(jìn)行回收,GC中用于回收的方法稱為收集器。

垃圾:不再被引用的對象。

由于GC需要消耗一些資源和時間,Java在對對象的生命周期特征進(jìn)行分析后,按照新生代、舊生代的方式來對對象進(jìn)行收集,以盡可能的縮短GC對應(yīng)用造成的暫停。

對新生代的對象的收集稱為minor GC;

對舊生代的對象的收集稱為Full GC;

程序中主動調(diào)用System.gc()的GC為Full GC。

Java垃圾回收是單獨的后臺線程gc執(zhí)行的,自動運行無需顯示調(diào)用。即使主動調(diào)用了java.lang.System.gc(),該方法也只會提醒系統(tǒng)進(jìn)行垃圾回收,但系統(tǒng)不一定會回應(yīng),可能會不予理睬




2. 判斷一塊內(nèi)存空間是否符合回收標(biāo)準(zhǔn):對象賦予了空值,且之后再未調(diào)用(obj = null;);對象賦予了新值,即重新分配了內(nèi)存空間(obj = new Obj();)。




3. 內(nèi)存泄漏:程序中保留著對永遠(yuǎn)不再使用的對象的引用。因此這些對象不回被GC回收,卻一直占用內(nèi)存空間卻毫無用處。即對象是可達(dá)的對象是無用的。

滿足這兩個條件即可判定為內(nèi)存泄漏

應(yīng)確保不需要的對象不可達(dá),通常采用將對象字段設(shè)置為null的方式,或從容器collection中移除對象。局部變量不再使用時無需顯示設(shè)置為null,因為對局部變量的引用會隨著方法的退出而自動清除。

內(nèi)存泄露的原因:全局集合;緩存;ClassLoader。




4. 不同的對象引用類型,GC會采用不同的方法進(jìn)行回收,JVM對象的引用分為了四種類型——

(1)強引用:默認(rèn)情況下,對象采用的均為強引用(這個對象的實例沒有其他對象

引用,GC時才會被回收)。

(2)軟引用:軟引用是Java中提供的一種比較適合于緩存場景的應(yīng)用(只有在內(nèi)存

不夠用的情況下才會被GC)。

(3)弱引用:在GC時一定會被GC回收。

(4)虛引用:由于虛引用只是用來得知對象是否被GC。


七、內(nèi)存調(diào)優(yōu)

1. 調(diào)優(yōu)目的減少GC的頻率尤其是Full GC的次數(shù),過多的GC會占用很多系統(tǒng)資源影響吞吐量。特別要關(guān)注Full GC,因為它會對整個堆進(jìn)行整理。




2.主要手段:JVM調(diào)優(yōu)主要通過配置JVM的參數(shù)來提高垃圾回收的速度,合理分配堆內(nèi)存各部分的比例。




3. 導(dǎo)致Full GC的幾種情況和調(diào)優(yōu)策略——

(1)舊生代空間不足:調(diào)優(yōu)時盡量讓對象在新生代GC時被回收、讓對象在新生代多

存活一段時間和不要創(chuàng)建過大的對象及數(shù)組避免直接在舊生代創(chuàng)建對象。

(2)持久代空間不足:增大PermGen空間,避免太多靜態(tài)對象。

(3)統(tǒng)計得到的GC后晉升到舊生代的平均大小大于舊生代剩余空間:控制好新生代

和舊生代的比例。

(4)System.gc()被顯示調(diào)用:垃圾回收不要手動觸發(fā),盡量依靠JVM自身的機

制。




4. 堆內(nèi)存比例不良設(shè)置會導(dǎo)致什么后果——

新生代設(shè)置過小:一是新生代GC次數(shù)非常頻繁,增大系統(tǒng)消耗;二是導(dǎo)致大對象直

接進(jìn)入舊生代,占據(jù)了舊生代剩余空間,誘發(fā)Full GC。

新生代設(shè)置過大:一是新生代設(shè)置過大會導(dǎo)致舊生代過?。ǘ芽偭恳欢ǎ?,從而誘發(fā)

Full GC;二是新生代GC耗時大幅度增加。

一般說來新生代占整個堆1/3比較合適。

Survivor設(shè)置過小:導(dǎo)致對象從eden直接到達(dá)舊生代,降低了在新生代的存活時

間。

Survivor設(shè)置過大:導(dǎo)致eden過小,增加了GC頻率。




5. JVM提供兩種較為簡單的GC策略的設(shè)置方式——

吞吐量優(yōu)先:JVM以吞吐量為指標(biāo),自行選擇相應(yīng)的GC策略及控制新生代與舊生代

的大小比例,來達(dá)到吞吐量指標(biāo)。這個值可由-XX:GCTimeRatio=n來設(shè)置。

暫停時間優(yōu)先:JVM以暫停時間為指標(biāo),自行選擇相應(yīng)的GC策略及控制新生代與舊

生代的大小比例,盡量保證每次GC造成的應(yīng)用停止時間都在指定的數(shù)值范圍內(nèi)完成。這

個值可由-XX:MaxGCPauseRatio=n來設(shè)置。


八、JVM常見配置

1. 堆設(shè)置——

-Xms:初始堆大小,

-Xmx:最大堆大小,

-XX:NewSize=n:設(shè)置年輕代大小,

-XX:NewRatio=n:設(shè)置年輕代和年老代的比值,

-XX:SurvivorRatio=n:年輕代中Eden區(qū)與兩個Survivor區(qū)的比值,

-XX:MaxPermSize=n:設(shè)置持久代大小。




2. 收集器設(shè)置——

-XX:+UseSerialGC:設(shè)置串行收集器,

-XX:+UseParallelGC:設(shè)置并行收集器,

-XX:+UseParalledlOldGC:設(shè)置并行年老代收集器,

-XX:+UseConcMarkSweepGC:設(shè)置并發(fā)收集器。




3. 垃圾回收統(tǒng)計信息——

-XX:+PrintGC,

-XX:+PrintGCDetails,

-XX:+PrintGCTimeStamps,

-Xloggc:filename。




4. 并行收集器設(shè)置——

-XX:ParallelGCThreads=n:設(shè)置并行收集器收集時使用的CPU數(shù)。并行收集線程

數(shù)。

-XX:MaxGCPauseMillis=n:設(shè)置并行收集最大暫停時間。

-XX:GCTimeRatio=n:設(shè)置垃圾回收時間占程序運行時間的百分比。公式為

1/(1+n)。




5. 并發(fā)收集器設(shè)置——

-XX:+CMSIncrementalMode:設(shè)置為增量模式。適用于單CPU情況。

-XX:ParallelGCThreads=n:設(shè)置并發(fā)收集器年輕代收集方式為并行收集時,使用的

CPU數(shù)。并行收集線程數(shù)。



關(guān)鍵詞:虛擬

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉