欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

JVM快速學(xué)習(xí)

JVM快速學(xué)習(xí)

公司主營(yíng)業(yè)務(wù):成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。成都創(chuàng)新互聯(lián)公司推出南芬免費(fèi)做網(wǎng)站回饋大家。

首先通過(guò)數(shù)據(jù)類型來(lái)引入一個(gè)高級(jí)語(yǔ)言的核心概念,堆和棧。JAVA的基本類型包括:byte, short, int, long, returnAddress等,其存儲(chǔ)在棧上;引用類型包括:類類型,接口類型和數(shù)組,其存儲(chǔ)在堆上。在java中,一個(gè)線程就會(huì)有相應(yīng)的線程棧與之對(duì)應(yīng),而堆則是所有線程共享的。棧是運(yùn)行單位,因此里面存儲(chǔ)的信息都是跟當(dāng)前線程相關(guān)信息的,包括局部變量、程序運(yùn)行狀態(tài)、方法返回值等;而堆只負(fù)責(zé)存儲(chǔ)對(duì)象信息。

之所以將對(duì)和棧分離,有如下幾點(diǎn)原因:棧代表了邏輯處理,而堆代表數(shù)據(jù),滿足分治的思想;堆中的內(nèi)容可以被多個(gè)棧共享,即提供數(shù)據(jù)交換的方式又節(jié)省空間;使得存儲(chǔ)地址動(dòng)態(tài)增長(zhǎng)成為可能,相應(yīng)棧中只需要記錄堆中的一個(gè)地址即可;對(duì)面向?qū)ο蟮脑忈?,?duì)象的屬性就是數(shù)據(jù),存放在堆中,對(duì)象的行為是運(yùn)行邏輯,放在棧中;堆和棧中,棧是程序運(yùn)行最根本的東西,程序運(yùn)行可以沒(méi)有堆,但不能沒(méi)有棧,而堆是為棧進(jìn)行數(shù)據(jù)存儲(chǔ)服務(wù)的,就是一塊共享的內(nèi)存,這種思想使得垃圾回收成為可能。

Java對(duì)象的大小:一個(gè)空Object對(duì)象的大小是8byte,以及其地址空間4byte(32位),比如對(duì)于int這個(gè)基礎(chǔ)類型,其包裝類型Integer大小為8+4=12byte,但由于java對(duì)象大小需要時(shí)8byte的倍數(shù),因而為16byte,因此包裝類型的消耗是基礎(chǔ)類型的2倍。

強(qiáng)引用、軟引用、弱引用和虛引用:強(qiáng)引用是一般虛擬機(jī)生成的引用,虛擬機(jī)嚴(yán)格的將通過(guò)它判斷是否需要回收;軟引用一般作為緩存使用,當(dāng)內(nèi)存緊張時(shí),會(huì)對(duì)其進(jìn)行回收;弱引用,也是作為緩存使用,不過(guò)一定會(huì)被垃圾回收。

 

JVM的組成,可以通過(guò)下圖對(duì)其有個(gè)大體的了解。

JVM快速學(xué)習(xí)

Class Loader:加載大Class文件,該文件的格式由《JVM Specification》規(guī)定,包括父類,接口,版本,字段,方法等元數(shù)據(jù)信息。

Execution Engine:執(zhí)行引擎也叫解釋器,負(fù)責(zé)解釋命令,提交OS執(zhí)行。所謂的JIT指的就是提前將中間語(yǔ)言字節(jié)碼轉(zhuǎn)化為目標(biāo)文件obj。

Native Interface:為了融合不同語(yǔ)言,java開(kāi)辟了一塊區(qū)域用于處理標(biāo)記為native的代碼,現(xiàn)在已很少使用。

Runtime data area:運(yùn)行數(shù)據(jù)區(qū)是JVM的重點(diǎn),所寫的程序就被加載在這兒。

此外,jvm的寄存器包括:pc,java程序計(jì)數(shù)器;optop,指向操作數(shù)棧頂?shù)闹羔?;frame,指向當(dāng)前執(zhí)行方法的執(zhí)行環(huán)境指針;vars,指向當(dāng)前執(zhí)行方法的局部變量區(qū)第一個(gè)變量的指針。

 

JVM的內(nèi)存管理,所有的數(shù)據(jù)都是放在運(yùn)行數(shù)據(jù)區(qū),接下來(lái)介紹其中最復(fù)雜的棧(Stack),也叫棧內(nèi)存,是java程序的運(yùn)行區(qū),在線程創(chuàng)建時(shí)創(chuàng)建,它的生命周期跟隨線程的生命周期,線程結(jié)束棧內(nèi)存就釋放,對(duì)于棧來(lái)說(shuō)不存在垃圾回收。棧中的數(shù)據(jù)是以棧幀(Stack Frame)來(lái)存放的,其是一塊內(nèi)存區(qū)塊,是一個(gè)有關(guān)方法和運(yùn)行期數(shù)據(jù)的數(shù)據(jù)集,當(dāng)方法A被調(diào)用時(shí)就產(chǎn)生一個(gè)棧幀F(xiàn)1,并壓入到棧中,A方法又調(diào)用了B方法,于是產(chǎn)生的棧幀F(xiàn)2也被壓入棧,執(zhí)行完畢后,先彈出F2,再?gòu)棾鯢1,遵循"先進(jìn)后出"原則,JAVA Stack的大體結(jié)構(gòu)如下所示。

JVM快速學(xué)習(xí)

 

JVM快速學(xué)習(xí)

回收算法的分類方式有很多,接下來(lái)通過(guò)一張表格對(duì)其進(jìn)行一個(gè)簡(jiǎn)單的介紹。

算法類別

原理闡述

按基本回收策略分

引用計(jì)數(shù)(Reference Counting)

針對(duì)某個(gè)對(duì)象,其每有一個(gè)引用,即增加一個(gè)計(jì)數(shù),刪除一個(gè)就減少一個(gè)計(jì)數(shù),垃圾回收時(shí)只收集計(jì)數(shù)為0的對(duì)象,缺點(diǎn)是無(wú)法處理循環(huán)引用的情況

標(biāo)記-清除(Mark-Sweep)

分為兩個(gè)階段,首先從引用根結(jié)點(diǎn)開(kāi)始標(biāo)識(shí)所有引用的對(duì)象,之后遍歷整個(gè)堆,把未標(biāo)記的對(duì)象刪除,此算法需要暫停整個(gè)應(yīng)用,同時(shí)會(huì)產(chǎn)生內(nèi)存碎片

復(fù)制(Copying)

把內(nèi)存空間劃分為2個(gè)相等區(qū)域,每次使用一個(gè),當(dāng)垃圾回收時(shí),遍歷當(dāng)前使用區(qū)域,把使用中對(duì)象賦值到另一個(gè)區(qū)域,該復(fù)制操作成本較小。并可以進(jìn)行內(nèi)存整理,缺點(diǎn)是需要兩倍的內(nèi)存空間

標(biāo)記-整理(Mark-Compact)

該算法結(jié)合了"標(biāo)記-清除"和"復(fù)制"的優(yōu)點(diǎn),第一階段從根結(jié)點(diǎn)開(kāi)始標(biāo)記對(duì)象,第二階段遍歷整個(gè)堆,清除未標(biāo)記對(duì)象并把存活對(duì)象壓縮到堆的其中一塊,按順序排放,同時(shí)解決碎片和空間問(wèn)題。

按分區(qū)對(duì)待的方式分

增量收集(Incremental Collecting)

實(shí)時(shí)垃圾回收,即在應(yīng)用進(jìn)行的同時(shí)進(jìn)行

分代收集(Generational Collecting)

基于對(duì)象生命周期分析得出的算法,把對(duì)象分為年輕代、年老代和持久代,對(duì)不同生命周期的對(duì)象使用不同的算法。

垃圾回收的判斷:由于引用計(jì)數(shù)方式無(wú)法解決循環(huán)引用,因而實(shí)際上,回收算法都是從根結(jié)點(diǎn)出發(fā),遍歷整個(gè)對(duì)象引用,查找存活對(duì)象。搜索的起點(diǎn)為棧(例如java的Main函數(shù))或者是運(yùn)行時(shí)的寄存器,通過(guò)其代表的引用找到堆中對(duì)象,逐步迭代,直到以null引用或基本類型結(jié)束,該結(jié)果是一個(gè)對(duì)象樹(shù),回收器會(huì)對(duì)未在該樹(shù)的對(duì)象進(jìn)行回收。

分代的概念:由于不同對(duì)象的生命周期不同,根據(jù)其自己的特點(diǎn)采取不同的收集方式可以大幅提高回收效率。比如與業(yè)務(wù)相關(guān)的對(duì)象一般生命周期較長(zhǎng),而臨時(shí)變量生命周期很短,通過(guò)分代,可以避免長(zhǎng)生命周期的對(duì)象被遍歷,以此來(lái)減少消耗。

如何分代:虛擬機(jī)分為年輕代(Young Generation)、年老代(Old Generation)和持久代(Permanent Generation)。所有新生成的對(duì)象首先是放在年輕代中,該代的目標(biāo)就是盡快回收那些短生命周期的對(duì)象,其分為3個(gè)區(qū),一個(gè)Eden區(qū),兩個(gè)Survior區(qū)。大部分對(duì)象在Eden區(qū)生成,當(dāng)該區(qū)滿時(shí),將存活對(duì)象復(fù)制到Survivor區(qū)(兩個(gè)中的一個(gè)),當(dāng)該區(qū)也滿了時(shí),將存活對(duì)象復(fù)制到另一個(gè)Survivor,當(dāng)這個(gè)Survivor也滿了時(shí),將從第一個(gè)Survivor區(qū)復(fù)制過(guò)來(lái)的并且還存活的對(duì)象復(fù)制到年老區(qū)Tenured,因此在年老區(qū)中主要存放生命周期較長(zhǎng)的對(duì)象。而持久代,用于存放靜態(tài)文件,如Java類、方法等。持久代對(duì)垃圾回收無(wú)顯著影響,但App使用較多反射時(shí),需要增加持久代的大小,通過(guò)設(shè)置-XX:MaxPermSize=<N>。接下來(lái)通過(guò)一張圖,對(duì)該部分有個(gè)宏觀的了解。

JVM快速學(xué)習(xí)

垃圾回收算法的觸發(fā):由于對(duì)象進(jìn)行了分代處理,因此垃圾回收的區(qū)域和時(shí)間也有了不同,主要包括如下兩種類型的GC。

Scavenge GC:一般當(dāng)新對(duì)象生成,并且在Eden申請(qǐng)空間失敗時(shí),觸發(fā)。將清除Eden區(qū)的非存活對(duì)象,并把存貨對(duì)象移動(dòng)到Survivor,然后整理兩個(gè)Survivor區(qū)。該方式不會(huì)影響到老年代,此外,該GC推薦使用速度快,效率高的算法,使Eden區(qū)盡快空閑出來(lái)。

Full GC:對(duì)整個(gè)堆進(jìn)行整理,包括Young、Tenured和Perm,因此為了提高系統(tǒng)性能,需要減少FullGC的次數(shù)。發(fā)生FullGC的場(chǎng)景有:年老代寫滿,持久代被寫滿和System.gc()被顯示調(diào)用,上一次GC后Heap各域分配策略動(dòng)態(tài)變化。

 接下來(lái)通過(guò)一個(gè)表格來(lái)連接不同的收集器的優(yōu)缺點(diǎn)。

收集器名稱

詮釋

串性收集

使用單線程處理所有垃圾回收,簡(jiǎn)單高效,適合數(shù)據(jù)量小的場(chǎng)景。通過(guò)-XX:+UseSerialGC打開(kāi)

并行收集

對(duì)年輕代進(jìn)行并行垃圾回收,因此可以減少垃圾回收時(shí)間,使用-XX:+UseParallelGC打開(kāi)。

可以對(duì)老年代進(jìn)行并行收集,默認(rèn)使用單線程垃圾回收,使用-XX:+UseParallelOldGC打開(kāi)

使用-XX:ParallelGCThreads=<N>設(shè)置并行垃圾回收的線程數(shù),此值可以和機(jī)器處理器數(shù)相等

通過(guò)-XX:MaxGCPauseMillis=<N>設(shè)置最大垃圾回收暫定時(shí)間

通過(guò)-XX:GCTimeRatio=<N>垃圾回收時(shí)間與非垃圾回收時(shí)間的比值,那么1/(1+N)即為當(dāng)先系統(tǒng)的吞吐量,N默認(rèn)值為99,即1%時(shí)間用于垃圾回收

并發(fā)收集

前兩者在垃圾回收時(shí),應(yīng)用會(huì)有明顯的暫停,該方式可以減少該影響,保證大部分工作并發(fā)進(jìn)行(應(yīng)用不停止),適合中大規(guī)模應(yīng)用,使用-XX:+UseConcMarkSweepGC打開(kāi),由于并發(fā)收集比較復(fù)雜,接下來(lái)介紹幾個(gè)基本概念。

浮動(dòng)垃圾:由于在應(yīng)用運(yùn)行時(shí)進(jìn)行垃圾回收,所有有些垃圾可能在垃圾回收進(jìn)行完成時(shí)產(chǎn)生,這樣就造成了"Floating Garbage",這些垃圾需要在下次垃圾回收周期才能回收,所以并發(fā)收集器需要保留20%的預(yù)留空間用于這些浮動(dòng)垃圾。

Concurrent Mode Failure:由于在垃圾回收時(shí)系統(tǒng)運(yùn)行,需要保證有足夠空間給程序使用,否則堆滿時(shí),會(huì)發(fā)生"并發(fā)模式失敗",整個(gè)應(yīng)用暫停,進(jìn)行垃圾回收??梢酝ㄟ^(guò)設(shè)置-XX:CMSInitiatingOccupancyFraction=<N>指定還有多少神域堆空間時(shí)開(kāi)始執(zhí)行并發(fā)收集

 

新一代的垃圾回收算法(Garbage First, G1):該算法是為大型應(yīng)用準(zhǔn)備的,支持很大的堆和高吞吐量。該算法簡(jiǎn)單來(lái)說(shuō),就是把整個(gè)堆劃分為一個(gè)個(gè)等大小的區(qū)域。內(nèi)存的回收和劃分都以region為單位,同時(shí)汲取CMS特點(diǎn),把垃圾回收過(guò)程分為幾個(gè)階段。G1在掃描了region以后,對(duì)其中的活躍對(duì)象的大小進(jìn)行排序,首先會(huì)收集那些活躍對(duì)象小的region,以便快速回收空間,因?yàn)榛钴S對(duì)象小,里面可以認(rèn)為多數(shù)都是垃圾,所有這種方式被稱為Garbage First,即垃圾優(yōu)先回收,整個(gè)垃圾回收過(guò)程包含如下幾個(gè)步驟。

初始標(biāo)記(Initial Marking):G1對(duì)于每個(gè)region都保存了兩個(gè)標(biāo)記用的bitmap,一個(gè)為previous marking bitmap,一個(gè)next marking bitmap,bitmap中包含了一個(gè)bit的地址信息指向?qū)ο蟮钠鹗键c(diǎn)。在開(kāi)始標(biāo)記前,首先并發(fā)的清空next marking bitmap,然后停止所有應(yīng)用線程,并掃描標(biāo)識(shí)出每個(gè)region中root可直接訪問(wèn)的對(duì)象,將region的top值放入next top at mark start(TAMS),之后恢復(fù)所有線程。

并發(fā)標(biāo)記(Concurrent Marking):按照之前的標(biāo)記掃描對(duì)象,以標(biāo)識(shí)這些對(duì)象的下層對(duì)象的活躍狀態(tài),將在此期間使用線程并發(fā)修改的先關(guān)記錄寫入remembered set logs中,新創(chuàng)建的對(duì)象則放入比top值更高的地址區(qū)間中,這些新創(chuàng)建的對(duì)象默認(rèn)狀態(tài)即為活躍的,同時(shí)修改top值。

最終標(biāo)記暫停(Final Marking Pause):當(dāng)應(yīng)用線程的remembered set logs未滿時(shí),是不會(huì)放入filled RS buffers中的,因此需要在此步驟中處理remembered set logs并修改相應(yīng)的remembered set。

存活對(duì)象計(jì)算并清除(Live Data Counting and Cleanup):該步驟的觸發(fā)依賴內(nèi)存空間是否達(dá)到H(H=(1-h)*HeapSize, h為JVM Heap大小的百分比閥值)。

 

JVM快速學(xué)習(xí)

JVM的相關(guān)配置項(xiàng)非常的多,首先通過(guò)一個(gè)通用的配置理解堆相關(guān)的配置。

Java –Xmx3550m –Xms3550m –Xmn2g –Xss128k –XX:NewRatio=4 –XX:SurvivorRatio=4 –xx:MaxPermSize=64m –XX:MaxTenuringThreshold=0

-Xmx3550:設(shè)置JVM最大可用內(nèi)存為3550M

-Xms3550:設(shè)置JVM的初始內(nèi)存為3550M,此值可以與最大內(nèi)存一致,避免每次垃圾回收后JVM重新分配內(nèi)存

-Xmn2g:設(shè)置年紀(jì)代大小為2G,整個(gè)堆大小=年輕代大小+年老代大小+持久代大小。持久代默認(rèn)大小為64m,所有增加年輕代會(huì)減少年老代大小,因此此值非常重要,推薦為整個(gè)堆大小的3/8

-Xss128k:設(shè)置線程的堆棧大小,默認(rèn)為1M,實(shí)際中需要根據(jù)應(yīng)用進(jìn)行調(diào)整,一般OS推薦的線程數(shù)為3000-5000。

-XX:NewRatio=4:設(shè)置年輕代與老年代的比值,即年親代占年老代的1/4。

-XX:SurvivorRatio=4:設(shè)置年輕代中Eden區(qū)域Survivor區(qū)的大小比值,設(shè)置為4,即兩個(gè)Survior區(qū)與一個(gè)Eden區(qū)的比值為2:4。

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

-XX:MaxTenuringThreshold=0:設(shè)置垃圾最大年齡,如果設(shè)置為0,則年輕代將不經(jīng)過(guò)Survivor區(qū),直接進(jìn)入老年代,適合老年代較多的場(chǎng)景。

 

接下里介紹吞吐量?jī)?yōu)先的并行收集器和響應(yīng)時(shí)間優(yōu)先的并發(fā)收集器。Tip:這類應(yīng)用推薦將年輕代設(shè)置的盡可能的大,尤其是吞吐量大的應(yīng)用。

并行收集器

java -Xmx3550m -Xms3550 –Xmn2g –Xss128k –XX:+UseParallelGC –XX:ParallelGCThreads=20 –XX:+UseParallelOldGC -XX:MaxGCPauseMillis=100 –XX:UseAdaptiveSizePolicy

-XX:+UseParallelGC:選擇年輕代的垃圾收集器為并行收集器

-XX:ParallelGCThreads=20:設(shè)置并行收集器的線程數(shù),最好和處理器數(shù)目一致

-XX:+UseParallelOldGC:配置年老代垃圾收集方式為并行收集

-XX:MaxGCPauseMillis=100:設(shè)置每次年輕代垃圾回收的最長(zhǎng)時(shí)間,如果滿足,則自動(dòng)調(diào)整年親代大小以滿足此值。

-XX:+UseAdaptiveSizePolicy:設(shè)置此選項(xiàng)后,并行收集器自動(dòng)選擇年輕代區(qū)大小和相應(yīng)Survivor區(qū)比例,推薦一直打開(kāi)。

 

并發(fā)收集器

java -Xmx3550m -Xms3550 –Xmn2g –Xss128k –XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC –XX:+UseParNewGC -XX:CMSFullGCBeforeCompaction=5 –XX:UseCMSCompactAtFullCollection

-XX:+UseConcMarkSweepGC(CMS):設(shè)置年老代為并發(fā)收集

-XX:+UseParNewGC:設(shè)置年輕代為并行收集,可以與CMS收集同時(shí)進(jìn)行,現(xiàn)有版本無(wú)需設(shè)置

-XX:CMSFullGCBeforeCompaction=5:設(shè)置運(yùn)行多少次GC后對(duì)內(nèi)存空間進(jìn)行壓縮、整理

-XX:UseCMSCompactAtFullCollection:打開(kāi)年老代的壓縮,可以消除碎片但會(huì)影響性能

此外,還有一些展示GC輔助信息的配置: -XX:PrintGC, -XX:+PrintGCDetails, -XX:PrintGCTimeStamps, Xloggc:filename。

 

JVM快速學(xué)習(xí)

Java內(nèi)存模型:不同的平臺(tái),內(nèi)存模型是不一樣的,但jvm內(nèi)存模型規(guī)范是統(tǒng)一的,java多線程并發(fā)問(wèn)題都會(huì)反映在java的內(nèi)存模型上,所謂線程安全就是要控制多個(gè)線程對(duì)某個(gè)資源的有序訪問(wèn)和修改??偨Y(jié)的Java的內(nèi)存模型,需要注意2個(gè)主要問(wèn)題:可見(jiàn)性和有序性

Tip:這部分內(nèi)容理解起來(lái)有一定難度,需要多復(fù)習(xí)。

可見(jiàn)性:多個(gè)線程之間是不能相互傳遞數(shù)據(jù)通信的,它們之間的溝通需要通過(guò)共享變量。Java內(nèi)存模型規(guī)定了jvm有主內(nèi)存,主內(nèi)存是多個(gè)線程共享的,當(dāng)new一個(gè)對(duì)象時(shí),也是被分配子啊主內(nèi)存中的,每個(gè)線程都有自己的工作內(nèi)存,工作內(nèi)存存儲(chǔ)了主存的某些對(duì)象的副本。當(dāng)線程操作某個(gè)對(duì)象時(shí),其執(zhí)行順序?yàn)椋簭闹鲀?nèi)復(fù)制變量當(dāng)前工作內(nèi)存(read and load);執(zhí)行代碼,改變共享變量值(use and assign);用工作內(nèi)存數(shù)據(jù)刷新主存相關(guān)內(nèi)容(store and write)。JVM規(guī)范定義了線程對(duì)主存的操作指令:read,load,use,assign,store,write。當(dāng)一個(gè)共享變量在多個(gè)線程的工作內(nèi)存中都有副本時(shí),如果一個(gè)線程修改了這個(gè)共享變量,那么其他線程應(yīng)該可以看到這個(gè)被修改后的值,這就是多線程的可見(jiàn)性問(wèn)題。

有序性:線程在引用變量時(shí)不能直接從主內(nèi)存中引用,如果線程工作內(nèi)存中沒(méi)有該變量,則會(huì)從主內(nèi)存中拷貝一個(gè)副本到工作內(nèi)存中,這個(gè)過(guò)程為read-load,完成后線程會(huì)引用該副本。當(dāng)同一線程再度引用該字段時(shí),就有可能重新從主內(nèi)存中獲取變量副本(read-load-use),也有可能直接引用原來(lái)的副本(use),也就是說(shuō)read,load,use順序可以有JVM實(shí)現(xiàn)系統(tǒng)決定。線程不能直接為主存中字段賦值,它會(huì)將值指定給工作內(nèi)存中的副本變量(assign),完成后這個(gè)變量副本會(huì)同步到主存儲(chǔ)去(store-write),至于何時(shí)同步過(guò)去,也有JVM決定。為了這部分操作的有序性,需要使用synchronized關(guān)鍵字,可以將方法變?yōu)橥椒椒╬ublic synchronized void add(),也可以增加同步變量static Object lock=new Object(),然后synchronized(lock)。每個(gè)鎖對(duì)象都有兩個(gè)隊(duì)列,一個(gè)是就緒隊(duì)列,一個(gè)是阻塞隊(duì)列,就緒隊(duì)列存儲(chǔ)了將要獲得鎖的線程,阻塞隊(duì)列存儲(chǔ)被阻塞的線程,當(dāng)一個(gè)線程被喚醒(nitify)后,才能進(jìn)入到就緒隊(duì)列,等待cpu調(diào)度。例如,當(dāng)一個(gè)線程a第一次執(zhí)行account.add方法是,jvm會(huì)檢查鎖對(duì)象account的就緒隊(duì)列是否已經(jīng)有線程在等待,如果有說(shuō)明account被占用,此時(shí)是第一次運(yùn)行,因此account就緒隊(duì)列為空,所以線程a獲得鎖,執(zhí)行方法。如果恰好這是線程b要執(zhí)行account.withdraw方法,由于線程a獲得的鎖還未釋放,因此b要進(jìn)入account的就緒隊(duì)列,等得到鎖再執(zhí)行。

簡(jiǎn)單來(lái)說(shuō),一個(gè)線程執(zhí)行臨界區(qū)代碼過(guò)程為:獲得同步鎖李晴空工作內(nèi)存;從主存拷貝變量副本到工作內(nèi)存;對(duì)這些變量進(jìn)行計(jì)算;將變量從工作內(nèi)存寫回到主存;釋放鎖。

生產(chǎn)者-消費(fèi)者模型:這是一個(gè)非常經(jīng)典的線程同步模型,有時(shí)不光需要保證多個(gè)線程多一個(gè)共享資源操作的互斥性,往往多個(gè)線程見(jiàn)都是有協(xié)作的,一個(gè)簡(jiǎn)單的例子如下所示。

JVM快速學(xué)習(xí) View Code

Volatile關(guān)鍵字:volatile是java的一種輕量級(jí)同步手段,它只提供多線程內(nèi)存的可見(jiàn)性,不保證執(zhí)行的有序性。其意義在于,任何線程對(duì)volatile修飾的變量進(jìn)行修改,都會(huì)馬上被其他線程讀取到,因?yàn)橹苯硬僮髦鞔?,沒(méi)有線程對(duì)工作內(nèi)存和主存同步。其使用場(chǎng)景為:對(duì)變量的寫操作不依賴于當(dāng)前值;該變量沒(méi)有包含在具有其他變量的不定式中。

 JVM調(diào)用工具:常見(jiàn)的包括Jconsole、JProfile和VisualVM,推薦使用VisualVM。所有的調(diào)優(yōu)都源于對(duì)線上應(yīng)用的監(jiān)控和分析,主要需要觀察內(nèi)存的釋放情況、集合類檢查、對(duì)象樹(shù)等。如下圖所示,通過(guò)查看集合實(shí)例的情況來(lái)分析。通過(guò)這類堆信息查看,可以分析出年老代年輕代劃分是否合理、內(nèi)存是否泄漏、垃圾回收算法是否合適等問(wèn)題。

JVM快速學(xué)習(xí)

此外,還可以通過(guò)線程監(jiān)控了解系統(tǒng)的線程數(shù)量和線程的狀態(tài),是否死鎖等;通過(guò)抽樣器查看CPU和內(nèi)存熱點(diǎn)的情況;通過(guò)快照來(lái)了解不同時(shí)刻相關(guān)狀態(tài)的差異。

內(nèi)存泄漏的檢查:內(nèi)存泄漏一般可以理解為系統(tǒng)資源在錯(cuò)誤使用的情況下,導(dǎo)致使用完畢的資源無(wú)法回收,從而導(dǎo)致新的資源分配請(qǐng)求無(wú)法完成,引起系統(tǒng)錯(cuò)誤。其常見(jiàn)場(chǎng)景為:年老代堆空間被占滿(java.lang.OutOfMemoryError:Java heap space),可以通過(guò)堆大小的變化發(fā)現(xiàn)問(wèn)題;持久代被占滿(java.lang.OutOfMemoryError:PermGen space),在大量使用反射時(shí)會(huì)出現(xiàn);堆棧溢出(java.lang.StackOverflowError),一般因?yàn)殄e(cuò)誤的遞歸和循環(huán)造成;線程堆棧滿(Fatal:Stack size too small),可以通過(guò)修改-Xss解決,不過(guò)還是主要注意是否是因?yàn)榫€程棧過(guò)深造成;系統(tǒng)內(nèi)存被占滿(java.lang.OutOfMemoryError:unable to create new native thread),由于OS沒(méi)有足夠的資源來(lái)產(chǎn)生線程造成的,可以考慮減少單個(gè)線程的消耗或重新設(shè)計(jì)這部分程序。

 

JVM快速學(xué)習(xí)

常見(jiàn)問(wèn)題

1.堆和棧的區(qū)別:堆是存放對(duì)象的,但是對(duì)象內(nèi)臨時(shí)變量是存在棧內(nèi)存中的。棧是跟隨線程的,有線程就有棧,堆是跟隨JVM的,有JVM就有堆內(nèi)存。

2.堆內(nèi)存中到底存在什么:對(duì)象,包括對(duì)象變量和對(duì)象方法。

3.類變量和實(shí)例變量有什么區(qū)別:靜態(tài)變量(有static修飾)是類變量,非靜態(tài)變量是實(shí)例變量。靜態(tài)變量存在方法區(qū)中,實(shí)例變量存在堆內(nèi)存中。有個(gè)說(shuō)法是類變量是在JVM啟動(dòng)時(shí)就初始化好了,其實(shí)不對(duì)。

4.Java的方法到底是傳值還是傳引用:都不是,而是以傳值的方式傳遞地址,具體的說(shuō)就是原始數(shù)據(jù)類型傳遞的值,引用類型傳遞的地址。對(duì)于原始數(shù)據(jù)類型,JVM的處理方法是從Method Area或Heap中拷貝到Stack,然后運(yùn)行Frame中方法,運(yùn)行完畢再將變量拷貝回去。

5.為什么會(huì)產(chǎn)生OutOfMemory:原因是Heap內(nèi)存中沒(méi)有可用空間了或永久區(qū)滿了,有時(shí)會(huì)發(fā)現(xiàn)對(duì)象不多仍出現(xiàn)該情況,一般是由繼承層次過(guò)多造成,因?yàn)镠eap中產(chǎn)生的對(duì)象都是先產(chǎn)生父類,然后產(chǎn)生子類。

6.為什么會(huì)產(chǎn)生StackOverFlowError:因?yàn)榫€程把??臻g消耗完了,一般都是遞歸函數(shù)造成的。

7.JVM中那些共享的,那些是私有的:Heap和Method Area是共享的,其他都是私有的。

8.還有那些需要注意的補(bǔ)充概念:常量池(constant pool),按照順序存放程序中的常量,且進(jìn)行索引編號(hào),默認(rèn)0到127放在常量池,string也是;安全管理器(Security Manager),提供java運(yùn)行期的安全控制,類加載器只有在通過(guò)認(rèn)證后才能加載class文件;方法索引表(Methods table),記錄每個(gè)method的地址信息,Stack和Heap中的地址指針其實(shí)指向Methods table的地址。

9.為什么不能調(diào)用System.gc():因?yàn)樵摬僮鲿?huì)進(jìn)行Full GC并停止所有活動(dòng)。

10.CGLib是什么:用于Spring和Hibernate等技術(shù)對(duì)類進(jìn)行增強(qiáng)時(shí),其可以直接操作字節(jié)碼動(dòng)態(tài)生成Class文件。

當(dāng)前標(biāo)題:JVM快速學(xué)習(xí)
分享網(wǎng)址:http://chinadenli.net/article40/giosho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、App設(shè)計(jì)、虛擬主機(jī)、搜索引擎優(yōu)化、定制網(wǎng)站、網(wǎng)站收錄

廣告

聲明:本網(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)

搜索引擎優(yōu)化