javagc,JAVAgcd

本文目錄一覽:

java列印gc日誌影響性能

我們可以在JVM中設置參數-XX:+PrintGC或者-verbose:gc,默認GC日誌是關閉的,但是如果想輸出GC詳細的日誌,可以增加其他的輔助參數。可以根據自己的需求增加

java中GC指的是什麼?

gc是指垃圾回收機制,當一個對象不能再被後續程序所引用到時,這個對象所佔用的內存空間就沒有存在的意義了,java虛擬機會不定時的去檢測內存中這樣的對象,然後回收這塊內存空間。

GC的基本原理:

對於程序員來說,用new關鍵字即在堆中分配了內存,我們稱之為「可達」。對於GC來說,只要所有被引用的對象為null時,我們稱之為「不可達」,就將進行內存的回收。

當一個對象被創建時,GC開始監控這個對象的大小、內存地址及使用情況。GC採用有向圖的方式記錄和管理堆(heap)中的所有對象,通過這種方式可以明確哪些對象是可達的,哪些不是。當確定為不可達時,則對其進行回收。

保證GC在不同平台的實現問題,java規範對其很多行為沒有進行嚴格的規定。對於採用什麼演算法,什麼時候進行回收等。

java方法區有沒有gc

java方法區是存在GC的

回收方法區

方法區即為永久代,主要回收兩部分內容:廢棄常量和無用類。

滿足以下3個條件的類稱之為無用類

該類所所有的對象實例已經被回收,也就是java堆中不存在該類的任何實例

載入該類的ClassLoader已經被回收

該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

在大量使用反射、動態代理、CGLib等ByteCode框架、動態生成JSP以及OSGI這類頻繁自定義ClassLoader的場景都需要虛擬機具備類卸載的功能,以保證永久帶不會溢出。

java中GC是什麼?為什麼要有GC?

GC是垃圾回收的意思(gabage collection),內存處理器是編程人員容易出現問題的地方,忘記或者錯誤的內存回收導致程序或者系統的不穩定甚至崩潰,java的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,java語言沒有提供釋放已分配內存的俄顯示操作方法。

希望能幫到你,謝謝!

IBM Java如何做到高性能GC的實現內幕

IBM JVM的GC分為三個步驟 Mark phase(標記) Sweep phase(清掃) Compaction phase(內存緊縮) 在了解這些過程之前 我們先看一下IBMJava中的對象的Layout和Heap lay out 一個Java對象在IBM vm中的結構如下 size+flags mptr locknflags objectdata size+flags   這是一個 byte的slot( 平台) 這個slot的主要功能就是描述對象的尺寸 由於IBMJava中的對象都是以 byte的倍數分配的 因此對象的尺寸其實就是真實尺寸/ 存放在 byte的slot中 另外在這個slot的低三位是保留欄位起到標記對象的作用 他們分別為 bit :swapped bit 這個交換位被用於Compaction phase即內存緊縮階段使用 同時 這一位在標記堆棧溢出的時候(mark stack overflow)也被用於標記NotYetScanned狀態 bit dosed bit 這個位用於標示這個對象是否被某個堆棧或者寄存器reference到了 如果這個標誌被至位則這個對象就不能在當前的GC cycle中被刪除 而且如果某個reference指向的內存不是一個真實的reference比如是一個簡單的float 或者integer變數但是它的值恰巧就是Heap中某個Object的地址的時候 我們就不能修改這個refernece 這種對象的bit 也被置為 bit :pinned bit 標記一個對象是否是一個一個釘扣對象(PINNED object) 一個Pinned Object也不能被GC刪除 因為他們可能在Heap之外被reference到了 典型的一個例子就是Thread 還記得我上面說的僵死縣城么?它不能被刪除的道理就是這個 另外一種PinnedObject就是 JNI Object 即被本地代碼使用的對象 Mptr: 在 平台上也是 byte的slot Mptr有兩個功能 如果mptr不是一個數組 則Mptr指向一個方法塊(method block) 你可以通過這個method block來得到一個類塊(class block) 這個類塊 告訴你這個Object是屬於哪個class的實例 method block和class block由Class Loader分配 而不是heap在heap中進行分配 如果mptr是一個數組(Array) mptr包含了這個對象中 數組的元素個數 lockflags 在 平台上也是 byte的slot 但是這個slot只有低 位被用到 bit :是array flag 如果這個位被置位 那麼這個對象就是一個數組同時mptr欄位就包含了數組的元素個數 bit 是hashed和moved bit 如果這個位被置位 那麼他就告訴我們這個對象在被hashed以後被刪除了 Object Data 就是這個對象本身的數據 Heap layout:  heap top  heap limit  heap base heap base是heap的起始地址 heap top是heap的結束地址 heaplimit 是當前程序使用的那段heap可以進行擴展和收縮的極限 你可以用 Xmx參數在java運行的時候對heap top和heap base進行控制 Alloc bits 和 mark bits  heap top allocmax markemax  heap limit alloc size marksize  heap base 上面這個結構描述了heap和alloc bits 以及 markbits之間的關係 allocbits和markbits都是元素為 個bit的vector 他們與heap有同樣的長度 下面是兩個對象被分配以後在heap和兩個vector中的表現 heaptop allocmax markmax heaplimit allocsize marksize object top object base object allocbit object markbit object top object base object allocbit 如上面的結構 如果一個對象在heap被alloc出來 那麼在allocbits中就標示出這個對象的起始地址所在的地址 allocbits中只標記起始地址 但是這個過程告訴我們這個對象在那裡被創建 但是不告訴我們這個對象是否存活 當在mark phase中如果某一個對象比如object 仍然存活 那麼就在markbits中對應的地址上標記一下The free list IBM jvm中的空閑塊用用一個free list鏈標示 如圖 freechunck freechunck freechunckn size size size next next next NULL freeStorage freeStorage freeste 有了這些基本概念我們來看看Mark phase的工作情況 MarkPhase GC的Mark phase將標記所有還活著的對象 這個標記所有可達對象的過程稱為tracing Jvm的活動狀態(active state)是由下面幾個部分組成的 每個線程的保存寄存器(saved registers) 描述線程的堆棧 Java類中的靜態元素 以及局部和全局的JNI(Java Native Interface)引用 在Jvm中的方法調用都在C Stack上引發一個Frame 這個Frame包含了 對象實例 為局部變數的assignment結果或者傳入方法的參數 所有這些引用在Tracing過程中都被同等對待 實際上 我們可以把一個線程的堆棧看城一系列 bytes slot的集合 然後對每一個堆棧都從頂向下對這些slot進行掃描 在掃描的過程中都必須校驗每個slot是否指向heap當中的一個真實的對象 因為在前面我就說過 很有可能這些slot值僅僅是一個int或float但是他們的值恰巧就等於heap中的一個對象地址 因此在掃描的時候必須相當的保守 掃描的時候必須保證所有的指針都是一個對象 而且這個對象沒有在GC中被刪除 只有符合下麵條件的slot才是一個指向對象的指針 必須以 byte的倍數分配的內存 必須在heap的範圍之內(即大於heapbase小於heaptop) 對應的allocbit必須置為 滿足這些條件的對象引用我們稱為roots 並且把他們的dosed bit置為 表示不能被GC刪除 我想大家已經知道C#中為何連Int和Float都是OBject的原因了吧 在C#中因為都是OBject因此 在tracing的過程中就減少了一次校驗 這個減少對性能起到很大的影響 如果掃描完成 那麼Tracing過程便能安全精確的執行 也就是說我們可以在roots中通過reference找到他對應的objects 由於他們是真實的reference 那麼我們就能夠在pactionphase中移動對應的對象並且修改這些reference Trace過程使用了一個可以容納 k的slots的stack 所有的引用逐個push進入這個堆棧並且同時在markbits中進行標記 當push和mark的工作完成之後 我們開始pop出這些slot並且進行trace 常規的對象(非數組對象)將通過mptr去訪問clas *** lock clas *** lock將會告訴我們從這個對象中找到的其他對象的reference在那裡?當我們在clas *** lock找到一個refernce以後 如果發現他沒有被mark 那麼我們就在markallocbits中mark他然後把他再壓入堆棧 數組對象利用mptr去訪問每個數組元素 如果他們沒有mark則mark然後壓入堆棧 Trace過程一直持續進行 直到堆棧為空 MarkStack OverFlow 由於markStack限制了尺寸 因此它可能會溢出 如果溢出發生 那麼我們就設定一個全局的標誌來表明發生了MarkStack OverFlow 然後我們將那些不能push入stack的OBject的bit 設定為NotYetScanned 然後當tracing過程完成以後 檢驗全局標誌如果發現有overflow則把NotYetScanned的對象再次壓入堆棧開始新的tracing過程 並行Mark(Parallel Mark) 由於使用逐位清掃(biise sweep)和內存緊縮規避功能 GC將化大部分的時間是用於Mark而非前面兩項 這就導致了IBM JVM需要開發一個GC的並行版本 並行GC的目的不是以犧牲單CPU系統上的效能來換取在 路對稱CPU系統上的高效率 並行Mark的基本思想就是通過多個輔助線程(helper thread)和一個共享工作的工具來減少Marking的時間 在單CPU系統中 執行GC工作的只有一個主線程 Parallel mark仍然需要這個主線程的參與 他充當了管理協調的角色 這個Thread所要執行的工作和單CPU上的一樣多 包括他必須掃描C Stack來鑒別需要收集的roots指針 一個有N路對稱CPU的系統自動含有n 個helper thread並且平均分布在每個CPU上 master thread將scan完的reference集合進行分塊 然後交給helper thread獨立完成mark工作 每個Helper thread都被分配了一個獨立的本地mark stack 以及一個shareable queue sharqueue將存放help thread在mark overflow的時候的NotyetScanned對象 然後由master thread將sharequeue中的對象balance到其他已經空閑的thread上去 並發Mark(Concurrent mark) Concurrent mark的主要目的在於當heap增長的時候減少GC的pause time 只要heap到達heap limit的時候 Concurrent mark就會被執行 在Concurrent phase中 GC要求應用中的每個線程(不是指helper thread而是應用程序自己開啟的線程以便充分利用系統資源)掃描他們自己的堆棧來得到roots 然後使用這些roots來同步的trace 可達對象 Tracing工作是由一個後台的低優先順序的線程執行 同時程序自己開啟的線程在分配內存的時候必須執行heap lock allocation 由於使用程序自己開啟的線程並發的執行mark live objects 我們必須紀錄那些已經trace過的object的變化 這個功能是採用一個叫寫閘(write barrier) 來實現的 這個寫閘在每次改變引用的時候被激活 它告訴我們什麼時候一個對象被跟新過了 以便我們從新掃描那部分heap 寫閘的具體實現是Heap會分配出 byte的內存段每個段都分配了一個byte在卡表中(card table) 無論何時一個對象的reference被更新cardtable將同步紀錄這個對象的起始地址 使用Byte而不用bit的原因是寫byte要比寫bit快 倍 而且我們可能希望空餘的bit會在未來被用到 當Concurrent mark執行完畢以後 S collection(stop total world)將會被執行 s的意思是指suspend所有程序自己開啟的線程 因此我們可以看到如果使用Concurrent mark那 lishixinzhi/Article/program/Java/JSP/201311/19555

深入理解 Java 之 GC 到底如何工作

Garbage Collection簡稱為GC,是垃圾回收的意思、內存處理器是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰。Java語言提供的GC功能可以自動的檢測對象是否超過作用域,從而達到自動回收內存的目的,java語言沒有提供釋放已分配內存的顯示操作方法,資源回收工作全部交由GC來完成,程序員不能精確的控制垃圾回收的時機。

GC在實現垃圾回收時的基本原理:

Java的內存管理實際就是對象的管理,其中包括對像的分配和釋放。對於程序員來說,分配對象使用new關鍵字,釋放對象時只是將對象賦值為null,讓程序員不能夠再訪問到這個對象,該對象被稱為「不可達」。GC將負責回收所有「不可達」對象的內存空間。

對於GC來說,當程序員創建對象時,GC就開始監控這個對象地址、大小以及使用情況。通常GC採用有向圖的方式記錄並管理堆中的所有對象,通過這種方式確定哪些對象是「可達」的,哪些對象是「不可達」的。當GC確定一些對象為「不可達時」GC就有責任回收這些內存空間,但為了GC能夠在不同的平台上實現,java規範對GC的很多行為都沒有進行嚴格的規定。例如對於採用什麼類型的回收演算法、什麼時候進行回收等重要問題都沒有明確的規定,因此不同的JVM實現著不同的的實現演算法,這也給JAVA程序員的開發帶來了很多不確定性。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/152188.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-12 00:55
下一篇 2024-11-12 00:55

發表回復

登錄後才能評論