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