摘要:第二步分析第一個(gè)循環(huán)即表示產(chǎn)生的對象,后面規(guī)律相同和會(huì)直接放入?yún)^(qū)。因?yàn)閮?yōu)先放區(qū),而且夠放,此時(shí)為兩者表示已用剩余。此值一般設(shè)置與相同以避免每次垃圾回收完后重新分配內(nèi)存設(shè)置年輕代大小為。
一、概述
閑來有空翻翻書,撿撿一些基礎(chǔ)點(diǎn),就當(dāng)靜下心多寫字。
Java基礎(chǔ)的東西無論怎么樣都會(huì)想到JVM,而提JVM必然想到最常見的一些點(diǎn):字節(jié)碼加載,類初始化,方法執(zhí)行,對象內(nèi)存分配和回收,線程和鎖機(jī)制等等。歸納整理的時(shí)候,怎么可以少了它們。不過,我打算換個(gè)方式,不寫太多概念(網(wǎng)上一搜一把的),想從一些代碼、例子、題目或者疑問等方面來寫寫。
JVM內(nèi)存管理需要理解的點(diǎn):內(nèi)存空間的劃分、內(nèi)存分配和內(nèi)存回收。
內(nèi)存空間:認(rèn)識方法區(qū)、堆區(qū)、本地方法棧等幾個(gè)空間,了解堆的分代管理。
內(nèi)存分配:在Java中這塊比較容易,就是棧和堆,而創(chuàng)建對象都在堆區(qū)。
內(nèi)存回收:實(shí)戰(zhàn)上最主要是關(guān)注什么時(shí)候會(huì)觸發(fā)回收(GC)和回收對性能的影響,學(xué)習(xí)上可以了解不同回收起和回收算法。
驗(yàn)證和測試需要的點(diǎn):常見的啟動(dòng)參數(shù)、GUI類工具。
常見的啟動(dòng)參數(shù):-Xms -Xmx -Xmn 等等
GUI類工具:JProfiler(推薦)、JVisualVM、MAT、JMap、JHat。
三、一個(gè)GC題目1)當(dāng)用-Xms30m -Xmx30m -Xmn10m -XX:+UseParallelGC 執(zhí)行上面的代碼時(shí)會(huì)執(zhí)行幾次Minor GC和幾次Full GC呢?
2)分別說明你的結(jié)果是如何推出來的?
public static void main(String[] args) throws Exception{ List
先思考下,別忙著往下看,萬一我的分析并不對呢?。?/strong>
先思考下,別忙著往下看,萬一我的分析并不對呢??!
先思考下,別忙著往下看,萬一我的分析并不對呢??!
第一步分析啟動(dòng)參數(shù):
首先,看到"UseParallelGC"參數(shù),表示這里采用的是“Parallel Scavenge+Serial Old”。那么,從回收器的類型,可以知道堆的新生代是基于復(fù)制算法的gc(即內(nèi)存模型有from和to區(qū)),堆的老年代則基于標(biāo)記-整理算法。
其次,看到"-Xms30m -Xmx30m"參數(shù),表示堆區(qū)最大為30M,且不會(huì)動(dòng)態(tài)擴(kuò)展。
最后,再看到"-Xmn10m"參數(shù),表示新生代區(qū)為10m,而且采用默認(rèn)的7.5:1,即Eden7.5M(7680k),而from和to區(qū)各為1.25M。
第二步分析第一個(gè)循環(huán)
i0(即表示i=0產(chǎn)生的對象,后面規(guī)律相同)和i1 會(huì)直接放入Eden區(qū)。因?yàn)閮?yōu)先放Eden區(qū),而且夠放,此時(shí)Eden為 6m/7.5m.(兩者表示 已用/剩余 。此處的6m為近似值,其他jvm對象之類占用內(nèi)存的,不細(xì)討論)。
i2來了,要放入Eden區(qū),發(fā)現(xiàn)空間不夠。觸發(fā)MinorGC。然后把i2放到Eden。
結(jié)果將i0~i1直接誒轉(zhuǎn)入老年代 ,原因是對象3m太大放不了From區(qū)(前面提到才1.25m)。
此時(shí)Eden區(qū) 3m/7.5m 老年代6m/20m
gc的log --> [PSYoungGen: 6451K->272K(8960K)] 6451K->6416K(29440K)
i3來了,直接繼續(xù)放入Eden區(qū)。 此時(shí)Eden區(qū) 6m/7.5m 老年代6m/20m
i4來了,跟i2一樣的情況,發(fā)現(xiàn)Eden不夠放了。再次觸發(fā)MinorGC。然后把i4放到Eden。
結(jié)果將i2~i3直接誒轉(zhuǎn)入老年代,去陪i0和i1了。
此時(shí)Eden區(qū) 3m/7.5m 老年代12m/20m
gc的log --> [PSYoungGen: 6650K->256K(8960K)] 12794K->12544K(29440K)
i5來了,繼續(xù)放入Eden區(qū),此時(shí)加上前面i4,Eden區(qū) 6m/7.5m 老年代12m/20m
i6來了,跟前面i2、i4情況一樣,觸發(fā)了一次MinorGC。然后把i6放到Eden。
結(jié)果: i6 在Eden,i0~i5 6個(gè)在老年代。 此時(shí)Eden區(qū) 3m/7.5m 老年代18m/20m
gc的log -->[PSYoungGen: 6453K->224K(8960K)] 18741K->18656K(29440K)
這里還多了一次FullGC。
gc的log -->[PSYoungGen: 240K->0K(8960K)] [PSOldGen: 18432K->18593K(20480K)]
暫時(shí)未能完全分析明白這點(diǎn),但gc日志來猜測,應(yīng)該是標(biāo)記-整理起作用了,為了整理出連續(xù)的空間吧。
第三步: 由于執(zhí)行了caches.clear(); 等于宣告前面的i0~i6的7個(gè)對象都不可用了(即GC Roots不可達(dá))
但還由于各區(qū)都有足夠大的空間,只要程序運(yùn)行未達(dá)到"GC安全點(diǎn)"是不會(huì)觸發(fā)GC的。
第四步:
j0來了,它會(huì)繼續(xù)放到Eden區(qū),此時(shí)陪著還沒回收的i6。
此時(shí)Eden區(qū) 6m/7.5m 老年代18m/20m
j1來了,這時(shí)候內(nèi)存管理會(huì)發(fā)現(xiàn)新生代和老年代都不夠空間申請了,即觸發(fā)FullGC。
結(jié)果:從老年代把不可用的i0~i5全部干掉,再把j0移入老年代,再把新生代中的i6干掉,然后j1放入新生代。
此時(shí)Eden區(qū) 3m/7.5m 老年代3m/20m
gc的log -->[PSYoungGen: 6178K->0K(8960K)] [PSOldGen: 18593K->3233K(20480K)]
運(yùn)行上面的程序,參數(shù)為: -Xms30m -Xmx30m -Xmn10m -XX:+UseParallelGC -XX:+PrintGCDetails
加上-XX:+PrintGCDetails,這樣可以打印GC的log情況來驗(yàn)證前面的分析。
ps:不同的虛擬機(jī)版本打印的輸出多少會(huì)有差異,以下log,是我在sum的1.6.0_43版本打印出來的,另外刪減掉一些不關(guān)心的輸出。
[GC [PSYoungGen: 6451K->320K(8960K)] [GC [PSYoungGen: 6698K->240K(8960K)] [GC [PSYoungGen: 6437K->240K(8960K)] [Full GC [PSYoungGen: 240K->0K(8960K)] [PSOldGen: 18432K->18594K(20480K)] 18672K->18594K(29440K) [Full GC [PSYoungGen: 6178K->0K(8960K)] [PSOldGen: 18594K->3234K(20480K)] 24773K->3234K(29440K) Heap PSYoungGen total 8960K, used 3248K >eden space 7680K, 42% used >from space 1280K, 0% used >to space 1280K, 0% used PSOldGen total 20480K, used 3234K PSPermGen total 21248K, used 3043K六、最后補(bǔ)充涉及到的知識點(diǎn) 6.1 關(guān)于堆區(qū)分代管理
新生代GC(Minor GC):主要是發(fā)生在新生代的收集動(dòng)作,據(jù)說IBM做過調(diào)查,絕大多數(shù)對象都是朝生夕死,所以MinorGC非常頻繁,速度也比較快。
老年代GC(Full GC):是指發(fā)生在老年代的收集動(dòng)作,但是通常也會(huì)對年輕代進(jìn)行垃圾收集。
-Xmx 設(shè)置JVM最大可用內(nèi)存為30M。
-Xms 設(shè)置JVM擴(kuò)展內(nèi)存為30M。(此值一般設(shè)置與-Xmx相同,以避免每次垃圾回收完后JVM重新分配內(nèi)存)
-Xmn:設(shè)置年輕代大小為10m。 (整個(gè)堆大小=年輕代大小 + 年老代大小 持久代大小 : 持久代PermGen是非堆的,可以通過jconsole查看)
-Xss128k:(設(shè)置每個(gè)線程的堆棧大小)
持久代,是通過PermSize和MaxPermSize
-XX:+UseParallelGC:選擇垃圾收集器為并行收集器。
串行處理器: 適用數(shù)據(jù)量比較?。?00M左右);單處理器下并且對響應(yīng)時(shí)間無要求的應(yīng)用。 缺點(diǎn):只能用于小型應(yīng)用
并行處理器: 適用“對吞吐量有高要求”,多CPU、對應(yīng)用響應(yīng)時(shí)間無要求的中、大型應(yīng)用。舉例:后臺處理、科學(xué)計(jì)算。 缺點(diǎn):應(yīng)用響應(yīng)時(shí)間可能較長
并發(fā)處理器: 適用“對響應(yīng)時(shí)間有高要求”,多CPU、對應(yīng)用響應(yīng)時(shí)間有較高要求的中、大型應(yīng)用。舉例:Web服務(wù)器/應(yīng)用服務(wù)器、電信交換、集成開發(fā)環(huán)境。
GC Roots不可達(dá):GC回收過程判斷對象是否可以回收的一種方式,叫可達(dá)性測試!
打印gc日志:啟動(dòng)程序時(shí)加vm參數(shù)-XX:+PrintGCDetails。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/65587.html
摘要:而字節(jié)碼運(yùn)行在之上,所以不用關(guān)心字節(jié)碼是在哪個(gè)操作系統(tǒng)編譯的,只要符合規(guī)范,那么,這個(gè)字節(jié)碼文件就是可運(yùn)行的。好處防止內(nèi)存中出現(xiàn)多份同樣的字節(jié)碼安全性角度特別說明類加載器在成功加載某個(gè)類之后,會(huì)把得到的類的實(shí)例緩存起來。 前言 只有光頭才能變強(qiáng) JVM在準(zhǔn)備面試的時(shí)候就有看了,一直沒時(shí)間寫筆記?,F(xiàn)在到了一家公司實(shí)習(xí),閑的時(shí)候就寫寫,刷刷JVM博客,刷刷電子書。 學(xué)習(xí)JVM的目的也很簡單...
摘要:在這種消耗很高的狀態(tài)下,應(yīng)用程序所有的線程都會(huì)掛起,暫停一切正常的工作,等待垃圾回收的完成。但是,因?yàn)榫€程切換和上下文轉(zhuǎn)換的消耗,會(huì)使得垃圾回收的總體成本上升,造成系統(tǒng)吞吐量的下降。 Java 垃圾回收(GC) 泛讀 文章地址: https://segmentfault.com/a/1190000008922319 0. 序言 帶著問題去看待 垃圾回收(GC) 會(huì)比較好,一般來說主要的...
摘要:當(dāng)一個(gè)實(shí)例被創(chuàng)建的時(shí)候,它最初被存放在堆內(nèi)存空間的年輕代的區(qū)中。老年代或者永久代是堆內(nèi)存的第二個(gè)邏輯部分。在垃圾回收過程中掃描屬于部分的堆內(nèi)存。一旦實(shí)例從堆內(nèi)存中刪除了,它們原來的位置將空出來給以后分配實(shí)例使用。 本文非原創(chuàng),翻譯自How Java Garbage Collection Works?在Java中為對象分配和釋放內(nèi)存空間都是由垃圾回收線程自動(dòng)執(zhí)行完成的。和C語言不一樣的是...
摘要:本人使用的是,以下涉及的默認(rèn)值均以該版本為準(zhǔn)。其中,新生代被細(xì)分為和兩個(gè)區(qū)域,這兩個(gè)區(qū)域分別被命名為和,以示區(qū)分。其中新生帶存放新生的對象或者年齡不大的對象,老年代則存放老年對象。 什么是垃圾回收機(jī)制 不定時(shí)去堆內(nèi)存中清理不可達(dá)對象。不可達(dá)的對象并不會(huì)馬上就會(huì)直接回收, 垃圾收集器在一個(gè)Java程序中的執(zhí)行是自動(dòng)的,不能強(qiáng)制執(zhí)行,即使程序員能明確地判斷出有一塊內(nèi)存已經(jīng)無用了,是應(yīng)該回收...
摘要:這個(gè)算法看似不錯(cuò)而且簡單,不過存在這一個(gè)致命傷當(dāng)兩個(gè)對象互相引用的時(shí)候,就永遠(yuǎn)不會(huì)被回收于是引用計(jì)數(shù)算法就永遠(yuǎn)回收不了這兩個(gè)對象,下面介紹另一種算法。 前言 ? 如果要問Java與其他編程語言最大的不同是什么,我第一個(gè)想到的一定就是Java所運(yùn)行的JVM所自帶的自動(dòng)垃圾回收機(jī)制,以下是我學(xué)習(xí)JVM垃圾回收機(jī)制整理的筆記,希望能對讀者有一些幫助。 哪些內(nèi)存需要回收?what? ? ...
閱讀 3486·2021-10-13 09:39
閱讀 1468·2021-10-08 10:05
閱讀 2273·2021-09-26 09:56
閱讀 2289·2021-09-03 10:28
閱讀 2688·2019-08-29 18:37
閱讀 2047·2019-08-29 17:07
閱讀 609·2019-08-29 16:23
閱讀 2200·2019-08-29 11:24