JVM的示例分析-創(chuàng)新互聯(lián)

小編給大家分享一下JVM的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

成都服務(wù)器托管,創(chuàng)新互聯(lián)提供包括服務(wù)器租用、成都服務(wù)器托管、帶寬租用、云主機(jī)、機(jī)柜租用、主機(jī)租用托管、CDN網(wǎng)站加速、申請(qǐng)域名等業(yè)務(wù)的一體化完整服務(wù)。電話咨詢:13518219792

追本溯源——堆和棧

堆通常是一個(gè)可以被看做一棵樹的數(shù)組對(duì)象,棧是一種只能在一端進(jìn)行插入和刪除操作的先進(jìn)后出線性表,JVM的本質(zhì)是堆和棧

第一,從軟件設(shè)計(jì)的角度看,棧代表了處理邏輯,而堆代表了數(shù)據(jù)。這樣分開,使得處理邏輯更為清晰。分而治之的思想。這種隔離、模塊化的思想在軟件設(shè)計(jì)的方方面面都有體現(xiàn)。

第二,堆與棧的分離,使得堆中的內(nèi)容可以被多個(gè)棧共享(也可以理解為多個(gè)線程訪問(wèn)同一個(gè)對(duì)象)。這種共享的收益是很多的。一方面這種共享提供了一種有效的數(shù)據(jù)交互方式(如:共享內(nèi)存),另一方面,堆中的共享常量和緩存可以被所有棧訪問(wèn),節(jié)省了空間。

第三,棧因?yàn)檫\(yùn)行時(shí)的需要,比如保存系統(tǒng)運(yùn)行的上下文,需要進(jìn)行地址段的劃分。由于棧只能向上增長(zhǎng),因此就會(huì)限制住棧存儲(chǔ)內(nèi)容的能力。而堆不同,堆中的對(duì)象是可以根據(jù)需要?jiǎng)討B(tài)增長(zhǎng)的,因此棧和堆的拆分,使得動(dòng)態(tài)增長(zhǎng)成為可能,相應(yīng)棧中只需記錄堆中的一個(gè)地址即可。

第四,面向?qū)ο缶褪嵌押蜅5耐昝澜Y(jié)合。其實(shí),面向?qū)ο蠓绞降某绦蚺c以前結(jié)構(gòu)化的程序在執(zhí)行上沒(méi)有任何區(qū)別。但是,面向?qū)ο蟮囊?,使得?duì)待問(wèn)題的思考方式發(fā)生了改變,而更接近于自然方式的思考。當(dāng)我們把對(duì)象拆開,你會(huì)發(fā)現(xiàn),對(duì)象的屬性其實(shí)就是數(shù)據(jù),存放在堆中;而對(duì)象的行為(方法),就是運(yùn)行邏輯,放在棧中。我們?cè)诰帉憣?duì)象的時(shí)候,其實(shí)即編寫了數(shù)據(jù)結(jié)構(gòu),也編寫的處理數(shù)據(jù)的邏輯。不得不承認(rèn),面向?qū)ο蟮脑O(shè)計(jì),確實(shí)很美。

JVM運(yùn)行機(jī)制

JVM的示例分析

此圖看出jvm內(nèi)存結(jié)構(gòu)

JVM內(nèi)存結(jié)構(gòu)主要包括兩個(gè)子系統(tǒng)和兩個(gè)組件。兩個(gè)子系統(tǒng)分別是Classloader子系統(tǒng)和Executionengine(執(zhí)行引擎)子系統(tǒng);兩個(gè)組件分別是Runtimedataarea(運(yùn)行時(shí)數(shù)據(jù)區(qū)域)組件和Nativeinterface(本地接口)組件。

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

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

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

RuntimeDataArea組件:這就是我們常說(shuō)的JVM的內(nèi)存了

JVM的生命周期

一、首先分析兩個(gè)概念

   JVM實(shí)例和JVM執(zhí)行引擎實(shí)例

 ?。?)JVM實(shí)例對(duì)應(yīng)了一個(gè)獨(dú)立運(yùn)行的java程序,它是進(jìn)程級(jí)別。

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

二、JVM的生命周期

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

  (2)JVM實(shí)例的運(yùn)行 main()作為該程序初始線程的起點(diǎn),任何其他線程均由該線程啟動(dòng)。JVM內(nèi)部有兩種線程:守護(hù)線程和非守護(hù)線程,main()屬于非守護(hù)線程,守護(hù)線程通常由JVM自己使用,java程序也可以標(biāo)明自己創(chuàng)建的線程是守護(hù)線程。

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

類的生命

JVM的示例分析

一個(gè)java類的完整的生命周期會(huì)經(jīng)歷加載、連接、初始化、使用、和卸載五個(gè)階段,當(dāng)然也有在加載或者連接之后沒(méi)有被初始化就直接被使用的情況

JVM的示例分析

雙親委派模型是一種組織類加載器之間關(guān)系的一種規(guī)范,他的工作原理是:如果一個(gè)類加載器收到了類加載的請(qǐng)求,它不會(huì)自己去嘗試加載這個(gè)類,而是把這個(gè)請(qǐng)求委派給父類加載器去完成,這樣層層遞進(jìn),最終所有的加載請(qǐng)求都被傳到最頂層的啟動(dòng)類加載器中,只有當(dāng)父類加載器無(wú)法完成這個(gè)加載請(qǐng)求(它的搜索范圍內(nèi)沒(méi)有找到所需的類)時(shí),才會(huì)交給子類加載器去嘗試加載.

認(rèn)識(shí)JVM內(nèi)存模型

對(duì)于JVM內(nèi)存,程序員只需要關(guān)注

  • 對(duì)象去哪兒——堆內(nèi)存(包括新生代和老年代,新生代又分為Enden區(qū)和兩個(gè)Survivor區(qū)),堆內(nèi)存用于存放對(duì)象,合理分區(qū)主要是為了提高垃圾回收效率,新創(chuàng)建的對(duì)象會(huì)在Enden區(qū),經(jīng)歷Minor GC后會(huì)到Survivor區(qū),經(jīng)歷一般15次GC還存活的話會(huì)進(jìn)入老年代。

  • 函數(shù)如何調(diào)用——棧內(nèi)存用于運(yùn)行線程,它們包含了方法里的臨時(shí)數(shù)據(jù)、堆里其它對(duì)象引用的特定數(shù)據(jù)。

  • 類去哪兒——方法區(qū)用來(lái)存儲(chǔ)類型信息(運(yùn)行時(shí)常量和靜態(tài)變量)和方法代碼和構(gòu)造函數(shù)代碼,通常也叫永久代,JDK8用元空間代替永久代

JVM資源一般分為兩種CPU和內(nèi)存,CPU代表著線程棧,內(nèi)存代表著堆,而往往生產(chǎn)環(huán)境JVM問(wèn)題一般都是這兩種資源不足導(dǎo)致的,當(dāng)線程棧使用不當(dāng)?shù)臅r(shí)候,通常會(huì)CPU爆滿,當(dāng)堆內(nèi)存使用不當(dāng)?shù)臅r(shí)候,通常會(huì)出現(xiàn)內(nèi)存溢出。

內(nèi)存管理清潔工——垃圾回收

Java程序語(yǔ)言中的一個(gè)大優(yōu)點(diǎn)是自動(dòng)垃圾回收,Java垃圾回收會(huì)找出沒(méi)用的對(duì)象,把它從內(nèi)存中移除并釋放出內(nèi)存給以后創(chuàng)建的對(duì)象使用。下面圖片生動(dòng)對(duì)比手動(dòng)垃圾回收和自動(dòng)垃圾回收的區(qū)別。垃圾回收重點(diǎn)關(guān)注碎片和性能。

初識(shí)垃圾回收算法

JVM的示例分析

按回收策略

(1).引用計(jì)數(shù)算法:

JVM的示例分析

給對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值就加1;當(dāng)引用失效時(shí),計(jì)數(shù)器值就減1;任何時(shí)刻計(jì)數(shù)器都為0的對(duì)象就是不再被使用的,垃圾收集器將回收該對(duì)象使用的內(nèi)存。引用計(jì)數(shù)算法實(shí)現(xiàn)簡(jiǎn)單,效率很高,微軟的COM技術(shù)、ActionScript、Python等都使用了引用計(jì)數(shù)算法進(jìn)行內(nèi)存管理,但是引用計(jì)數(shù)算法對(duì)于對(duì)象之間相互循環(huán)引用問(wèn)題難以解決,因此java并沒(méi)有使用引用計(jì)數(shù)算法。

(2).根搜索算法:

JVM的示例分析

通過(guò)一系列的名為“GC Root”的對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)向下搜索,搜索所走過(guò)的路徑稱為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Root沒(méi)有任何引用鏈相連時(shí),則該對(duì)象不可達(dá),該對(duì)象是不可使用的,垃圾收集器將回收其所占的內(nèi)存。

在Java語(yǔ)言里,可作為GC Roots對(duì)象的包括如下幾種:

a.System Class,像rt.jar里面的java.util.*

b.Thread,開始狀態(tài)的線程

c.虛擬機(jī)棧(棧楨中的本地變量表)中的引用的對(duì)象

d.方法區(qū)中的類靜態(tài)屬性引用的對(duì)象

e.方法區(qū)中的常量引用的對(duì)象

f.本地方法棧中JNI的引用的對(duì)象

(3).標(biāo)記-清除算法:

JVM的示例分析

最基礎(chǔ)的垃圾收集算法,算法分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成之后統(tǒng)一回收掉所有被標(biāo)記的對(duì)象。

標(biāo)記-清除算法的缺點(diǎn)有兩個(gè):首先,效率問(wèn)題,標(biāo)記和清除效率都不高。其次,標(biāo)記清除之后會(huì)產(chǎn)生大量的不連續(xù)的內(nèi)存碎片,空間碎片太多會(huì)導(dǎo)致當(dāng)程序需要為較大對(duì)象分配內(nèi)存時(shí)無(wú)法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。

(4).復(fù)制算法:

JVM的示例分析

將可用內(nèi)存按容量分成大小相等的兩塊,每次只使用其中一塊,當(dāng)這塊內(nèi)存使用完了,就將還存活的對(duì)象復(fù)制到另一塊內(nèi)存上去,然后把使用過(guò)的內(nèi)存空間一次清理掉。這樣使得每次都是對(duì)其中一塊內(nèi)存進(jìn)行回收,內(nèi)存分配時(shí)不用考慮內(nèi)存碎片等復(fù)雜情況,只需要移動(dòng)堆頂指針,按順序分配內(nèi)存即可,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效。

復(fù)制算法的缺點(diǎn)顯而易見,可使用的內(nèi)存降為原來(lái)一半。

(5).標(biāo)記-清除-整理算法:

標(biāo)記-整理算法在標(biāo)記-清除算法基礎(chǔ)上做了改進(jìn),標(biāo)記階段是相同的標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成之后不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),在移動(dòng)過(guò)程中清理掉可回收的對(duì)象,這個(gè)過(guò)程叫做整理。

標(biāo)記-整理算法相比標(biāo)記-清除算法的優(yōu)點(diǎn)是內(nèi)存被整理以后不會(huì)產(chǎn)生大量不連續(xù)內(nèi)存碎片問(wèn)題。

復(fù)制算法在對(duì)象存活率高的情況下就要執(zhí)行較多的復(fù)制操作,效率將會(huì)變低,而在對(duì)象存活率高的情況下使用標(biāo)記-整理算法效率會(huì)大大提高。

按分區(qū)回收

(1).分代算法:

根據(jù)對(duì)象的存活周期的不同將內(nèi)存劃分為幾塊。一般把java堆分為新生代和老年代,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴?。在新生代,每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活,那就選用復(fù)制算法,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集。而老年代中因?yàn)閷?duì)象存活率高、沒(méi)有額外空間對(duì)他進(jìn)行分配擔(dān)保,就必須使用“標(biāo)記-整理”算法進(jìn)行回收。

按系統(tǒng)線程

串行/并行回收方式:在GC過(guò)程中,單線程/多線程收集器采用Stop-the-World機(jī)制,做事專一吞吐量高;

并發(fā)回收:工作線程和垃圾回收線程并發(fā)執(zhí)行,一心二用,吞吐量較低,不過(guò)保證在GC的時(shí)候,其它用戶線程可以工作;

垃圾收集器

JVM的示例分析

JVM常見參數(shù)

最后匯總一下JVM常見配置

類加載設(shè)置

-XX:+TraceClassLoading:類加載日志

-XX:+TraceClassUnloading:類卸載日志

堆設(shè)置

-Xms:初始堆大小

-Xmx:大堆大小

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

-XX:NewRatio=n:設(shè)置年輕代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代占整個(gè)年輕代年老代和的1/4

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

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

收集器設(shè)置

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

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

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

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

垃圾回收統(tǒng)計(jì)信息

-XX:+PrintGC

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:filename

并行收集器設(shè)置

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

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

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

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

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

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

以上是“JVM的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道!

本文標(biāo)題:JVM的示例分析-創(chuàng)新互聯(lián)
當(dāng)前鏈接:http://bm7419.com/article48/gichp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、外貿(mào)網(wǎng)站建設(shè)、自適應(yīng)網(wǎng)站云服務(wù)器、網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)