欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
JVM 垃圾回收器工作原理及使用實(shí)例介紹

Java 語(yǔ)言的一大特點(diǎn)就是可以進(jìn)行自動(dòng)垃圾回收處理,而無(wú)需開(kāi)發(fā)人員過(guò)于關(guān)注系統資源,例如內存資源的釋放情況。自動(dòng)垃圾收集雖然大大減輕了開(kāi)發(fā)人員的工作量,但是也增加了軟件系統的負擔。

擁有垃圾收集器可以說(shuō)是 Java 語(yǔ)言與 C 語(yǔ)言的一項顯著(zhù)區別。在 C 語(yǔ)言中,程序員必須小心謹慎地處理每一項內存分配,且內存使用完后必須手工釋放曾經(jīng)占用的內存空間。當內存釋放不夠完全時(shí),即存在分配但永不釋放的內存塊,就會(huì )引起內存泄漏,嚴重時(shí)甚至導致程序癱瘓。

以下列舉了垃圾回收器常用的算法及實(shí)驗原理:

  • 引用計數法 (Reference Counting)

引用計數器在微軟的 COM 組件技術(shù)中、Adobe 的 ActionScript3 種都有使用。

引用計數器的實(shí)現很簡(jiǎn)單,對于一個(gè)對象 A,只要有任何一個(gè)對象引用了 A,則 A 的引用計數器就加 1,當引用失效時(shí),引用計數器就減 1。只要對象 A 的引用計數器的值為 0,則對象 A 就不可能再被使用。

引用計數器的實(shí)現也非常簡(jiǎn)單,只需要為每個(gè)對象配置一個(gè)整形的計數器即可。但是引用計數器有一個(gè)嚴重的問(wèn)題,即無(wú)法處理循環(huán)引用的情況。因此,在 Java 的垃圾回收器中沒(méi)有使用這種算法。

一個(gè)簡(jiǎn)單的循環(huán)引用問(wèn)題描述如下:有對象 A 和對象 B,對象 A 中含有對象 B 的引用,對象 B 中含有對象 A 的引用。此時(shí),對象 A 和對象 B 的引用計數器都不為 0。但是在系統中卻不存在任何第 3 個(gè)對象引用了 A 或 B。也就是說(shuō),A 和 B 是應該被回收的垃圾對象,但由于垃圾對象間相互引用,從而使垃圾回收器無(wú)法識別,引起內存泄漏。

  • 標記-清除算法 (Mark-Sweep)

標記-清除算法將垃圾回收分為兩個(gè)階段:標記階段和清除階段。一種可行的實(shí)現是,在標記階段首先通過(guò)根節點(diǎn),標記所有從根節點(diǎn)開(kāi)始的較大對象。因此,未被標記的對象就是未被引用的垃圾對象。然后,在清除階段,清除所有未被標記的對象。該算法最大的問(wèn)題是存在大量的空間碎片,因為回收后的空間是不連續的。在對象的堆空間分配過(guò)程中,尤其是大對象的內存分配,不連續的內存空間的工作效率要低于連續的空間。

  • 復制算法 (Copying)

將現有的內存空間分為兩快,每次只使用其中一塊,在垃圾回收時(shí)將正在使用的內存中的存活對象復制到未被使用的內存塊中,之后,清除正在使用的內存塊中的所有對象,交換兩個(gè)內存的角色,完成垃圾回收。

如果系統中的垃圾對象很多,復制算法需要復制的存活對象數量并不會(huì )太大。因此在真正需要垃圾回收的時(shí)刻,復制算法的效率是很高的。又由于對象在垃圾回收過(guò)程中統一被復制到新的內存空間中,因此,可確?;厥蘸蟮膬却婵臻g是沒(méi)有碎片的。該算法的缺點(diǎn)是將系統內存折半。

Java 的新生代串行垃圾回收器中使用了復制算法的思想。新生代分為 eden 空間、from 空間、to 空間 3 個(gè)部分。其中 from 空間和 to 空間可以視為用于復制的兩塊大小相同、地位相等,且可進(jìn)行角色互換的空間塊。from 和 to 空間也稱(chēng)為 survivor 空間,即幸存者空間,用于存放未被回收的對象。

在垃圾回收時(shí),eden 空間中的存活對象會(huì )被復制到未使用的 survivor 空間中 (假設是 to),正在使用的 survivor 空間 (假設是 from) 中的年輕對象也會(huì )被復制到 to 空間中 (大對象,或者老年對象會(huì )直接進(jìn)入老年帶,如果 to 空間已滿(mǎn),則對象也會(huì )直接進(jìn)入老年代)。此時(shí),eden 空間和 from 空間中的剩余對象就是垃圾對象,可以直接清空,to 空間則存放此次回收后的存活對象。這種改進(jìn)的復制算法既保證了空間的連續性,又避免了大量的內存空間浪費。

  • 標記-壓縮算法 (Mark-Compact)

復制算法的高效性是建立在存活對象少、垃圾對象多的前提下的。這種情況在年輕代經(jīng)常發(fā)生,但是在老年代更常見(jiàn)的情況是大部分對象都是存活對象。如果依然使用復制算法,由于存活的對象較多,復制的成本也將很高。

標記-壓縮算法是一種老年代的回收算法,它在標記-清除算法的基礎上做了一些優(yōu)化。也首先需要從根節點(diǎn)開(kāi)始對所有可達對象做一次標記,但之后,它并不簡(jiǎn)單地清理未標記的對象,而是將所有的存活對象壓縮到內存的一端。之后,清理邊界外所有的空間。這種方法既避免了碎片的產(chǎn)生,又不需要兩塊相同的內存空間,因此,其性?xún)r(jià)比比較高。

  • 增量算法 (Incremental Collecting)

在垃圾回收過(guò)程中,應用軟件將處于一種 CPU 消耗很高的狀態(tài)。在這種 CPU 消耗很高的狀態(tài)下,應用程序所有的線(xiàn)程都會(huì )掛起,暫停一切正常的工作,等待垃圾回收的完成。如果垃圾回收時(shí)間過(guò)長(cháng),應用程序會(huì )被掛起很久,將嚴重影響用戶(hù)體驗或者系統的穩定性。

增量算法的基本思想是,如果一次性將所有的垃圾進(jìn)行處理,需要造成系統長(cháng)時(shí)間的停頓,那么就可以讓垃圾收集線(xiàn)程和應用程序線(xiàn)程交替執行。每次,垃圾收集線(xiàn)程只收集一小片區域的內存空間,接著(zhù)切換到應用程序線(xiàn)程。依次反復,直到垃圾收集完成。使用這種方式,由于在垃圾回收過(guò)程中,間斷性地還執行了應用程序代碼,所以能減少系統的停頓時(shí)間。但是,因為線(xiàn)程切換和上下文轉換的消耗,會(huì )使得垃圾回收的總體成本上升,造成系統吞吐量的下降。

  • 分代 (Generational Collecting)

根據垃圾回收對象的特性,不同階段最優(yōu)的方式是使用合適的算法用于本階段的垃圾回收,分代算法即是基于這種思想,它將內存區間根據對象的特點(diǎn)分成幾塊,根據每塊內存區間的特點(diǎn),使用不同的回收算法,以提高垃圾回收的效率。以 Hot Spot 虛擬機為例,它將所有的新建對象都放入稱(chēng)為年輕代的內存區域,年輕代的特點(diǎn)是對象會(huì )很快回收,因此,在年輕代就選擇效率較高的復制算法。當一個(gè)對象經(jīng)過(guò)幾次回收后依然存活,對象就會(huì )被放入稱(chēng)為老生代的內存空間。在老生代中,幾乎所有的對象都是經(jīng)過(guò)幾次垃圾回收后依然得以幸存的。因此,可以認為這些對象在一段時(shí)期內,甚至在應用程序的整個(gè)生命周期中,將是常駐內存的。如果依然使用復制算法回收老生代,將需要復制大量對象。再加上老生代的回收性?xún)r(jià)比也要低于新生代,因此這種做法也是不可取的。根據分代的思想,可以對老年代的回收使用與新生代不同的標記-壓縮算法,以提高垃圾回收效率。

從不同角度分析垃圾收集器,可以將其分為不同的類(lèi)型。

1. 按線(xiàn)程數分,可以分為串行垃圾回收器和并行垃圾回收器。串行垃圾回收器一次只使用一個(gè)線(xiàn)程進(jìn)行垃圾回收;并行垃圾回收器一次將開(kāi)啟多個(gè)線(xiàn)程同時(shí)進(jìn)行垃圾回收。在并行能力較強的 CPU 上,使用并行垃圾回收器可以縮短 GC 的停頓時(shí)間。

2. 按照工作模式分,可以分為并發(fā)式垃圾回收器和獨占式垃圾回收器。并發(fā)式垃圾回收器與應用程序線(xiàn)程交替工作,以盡可能減少應用程序的停頓時(shí)間;獨占式垃圾回收器 (Stop the world) 一旦運行,就停止應用程序中的其他所有線(xiàn)程,直到垃圾回收過(guò)程完全結束。

3. 按碎片處理方式可分為壓縮式垃圾回收器和非壓縮式垃圾回收器。壓縮式垃圾回收器會(huì )在回收完成后,對存活對象進(jìn)行壓縮整理,消除回收后的碎片;非壓縮式的垃圾回收器不進(jìn)行這步操作。

4. 按工作的內存區間,又可分為新生代垃圾回收器和老年代垃圾回收器。

可以用以下指標評價(jià)一個(gè)垃圾處理器的好壞。

吞吐量:指在應用程序的生命周期內,應用程序所花費的時(shí)間和系統總運行時(shí)間的比值。系統總運行時(shí)間=應用程序耗時(shí) GC 耗時(shí)。如果系統運行了 100min,GC 耗時(shí) 1min,那么系統的吞吐量就是 (100-1)/100=99%。

垃圾回收器負載:和吞吐量相反,垃圾回收器負載指來(lái)記回收器耗時(shí)與系統運行總時(shí)間的比值。

停頓時(shí)間:指垃圾回收器正在運行時(shí),應用程序的暫停時(shí)間。對于獨占回收器而言,停頓時(shí)間可能會(huì )比較長(cháng)。使用并發(fā)的回收器時(shí),由于垃圾回收器和應用程序交替運行,程序的停頓時(shí)間會(huì )變短,但是,由于其效率很可能不如獨占垃圾回收器,故系統的吞吐量可能會(huì )較低。

垃圾回收頻率:指垃圾回收器多長(cháng)時(shí)間會(huì )運行一次。一般來(lái)說(shuō),對于固定的應用而言,垃圾回收器的頻率應該是越低越好。通常增大堆空間可以有效降低垃圾回收發(fā)生的頻率,但是可能會(huì )增加回收產(chǎn)生的停頓時(shí)間。

反應時(shí)間:指當一個(gè)對象被稱(chēng)為垃圾后多長(cháng)時(shí)間內,它所占據的內存空間會(huì )被釋放。

堆分配:不同的垃圾回收器對堆內存的分配方式可能是不同的。一個(gè)良好的垃圾收集器應該有一個(gè)合理的堆內存區間劃分。

JVM 垃圾回收器分類(lèi)

  • 新生代串行收集器

串行收集器主要有兩個(gè)特點(diǎn):第一,它僅僅使用單線(xiàn)程進(jìn)行垃圾回收;第二,它獨占式的垃圾回收。

在串行收集器進(jìn)行垃圾回收時(shí),Java 應用程序中的線(xiàn)程都需要暫停,等待垃圾回收的完成,這樣給用戶(hù)體驗造成較差效果。雖然如此,串行收集器卻是一個(gè)成熟、經(jīng)過(guò)長(cháng)時(shí)間生產(chǎn)環(huán)境考驗的極為高效的收集器。新生代串行處理器使用復制算法,實(shí)現相對簡(jiǎn)單,邏輯處理特別高效,且沒(méi)有線(xiàn)程切換的開(kāi)銷(xiāo)。在諸如單 CPU 處理器或者較小的應用內存等硬件平臺不是特別優(yōu)越的場(chǎng)合,它的性能表現可以超過(guò)并行回收器和并發(fā)回收器。在 HotSpot 虛擬機中,使用-XX: UseSerialGC 參數可以指定使用新生代串行收集器和老年代串行收集器。當 JVM 在 Client 模式下運行時(shí),它是默認的垃圾收集器。一次新生代串行收集器的工作輸出日志類(lèi)似如清單 1 信息 (使用-XX: PrintGCDetails 開(kāi)關(guān)) 所示。

清單 1. 一次新生代串行收集器的工作輸出日志
1
2
3
4
[GC [DefNew: 3468K->150K(9216K), 0.0028638 secs][Tenured:
  1562K->1712K(10240K), 0.0084220 secs] 3468K->1712K(19456K),
  [Perm : 377K->377K(12288K)],
  0.0113816 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

它顯示了一次垃圾回收前的新生代的內存占用量和垃圾回收后的新生代內存占用量,以及垃圾回收所消耗的時(shí)間。

  • 老年代串行收集器

老年代串行收集器使用的是標記-壓縮算法。和新生代串行收集器一樣,它也是一個(gè)串行的、獨占式的垃圾回收器。由于老年代垃圾回收通常會(huì )使用比新生代垃圾回收更長(cháng)的時(shí)間,因此,在堆空間較大的應用程序中,一旦老年代串行收集器啟動(dòng),應用程序很可能會(huì )因此停頓幾秒甚至更長(cháng)時(shí)間。雖然如此,老年代串行回收器可以和多種新生代回收器配合使用,同時(shí)它也可以作為 CMS 回收器的備用回收器。若要啟用老年代串行回收器,可以嘗試使用以下參數:-XX: UseSerialGC: 新生代、老年代都使用串行回收器。

清單 2. 一次老年代串行收集器的工作輸出日志
1
2
3
4
5
6
7
8
9
10
11
Heap
 def new generation total 4928K, used 1373K [0x27010000, 0x27560000, 0x2c560000)
 eden space 4416K, 31% used [0x27010000, 0x27167628, 0x27460000)
 from space 512K, 0% used [0x27460000, 0x27460000, 0x274e0000)
 to space 512K, 0% used [0x274e0000, 0x274e0000, 0x27560000)
 tenured generation total 10944K, used 0K [0x2c560000, 0x2d010000, 0x37010000)
 the space 10944K, 0% used [0x2c560000, 0x2c560000, 0x2c560200, 0x2d010000)
 compacting perm gen total 12288K, used 376K [0x37010000, 0x37c10000, 0x3b010000)
 the space 12288K, 3% used [0x37010000, 0x3706e0b8, 0x3706e200, 0x37c10000)
 ro space 10240K, 51% used [0x3b010000, 0x3b543000, 0x3b543000, 0x3ba10000)
 rw space 12288K, 55% used [0x3ba10000, 0x3c0ae4f8, 0x3c0ae600, 0x3c610000)

如果使用-XX: UseParNewGC 參數設置,表示新生代使用并行收集器,老年代使用串行收集器,如清單 3 所示。

清單 3. 一次串并行收集器混合使用的工作輸出日志
1
2
3
4
5
6
7
8
9
10
Heap
 par new generation total 4928K, used 1373K [0x0f010000, 0x0f560000, 0x14560000)
 eden space 4416K, 31% used [0x0f010000, 0x0f167620, 0x0f460000)
 from space 512K, 0% used [0x0f460000, 0x0f460000, 0x0f4e0000)
 to space 512K, 0% used [0x0f4e0000, 0x0f4e0000, 0x0f560000)
 tenured generation total 10944K, used 0K [0x14560000, 0x15010000, 0x1f010000)
 the space 10944K, 0% used [0x14560000, 0x14560000, 0x14560200, 0x15010000)
 compacting perm gen total 12288K, used 2056K [0x1f010000, 0x1fc10000, 0x23010000)
 the space 12288K, 16% used [0x1f010000, 0x1f2121d0, 0x1f212200, 0x1fc10000)
No shared spaces configured.

如果使用-XX: UseParallelGC 參數設置,表示新生代和老年代均使用并行回收收集器。如清單 4 所示。

清單 4. 一次老年代并行回收器的工作輸出日志
1
2
3
[Full GC [Tenured: 1712K->1699K(10240K), 0.0071963 secs] 1712K->1699K(19456K),
      [Perm : 377K->372K(12288K)], 0.0072393 secs] [Times: user=0.00 sys=0.00,
      real=0.01 secs]

它顯示了垃圾回收前老年代和永久區的內存占用量,以及垃圾回收后老年代和永久區的內存使用量。

  • 并行收集器

并行收集器是工作在新生代的垃圾收集器,它只簡(jiǎn)單地將串行回收器多線(xiàn)程化。它的回收策略、算法以及參數和串行回收器一樣。

并行回收器也是獨占式的回收器,在收集過(guò)程中,應用程序會(huì )全部暫停。但由于并行回收器使用多線(xiàn)程進(jìn)行垃圾回收,因此,在并發(fā)能力比較強的 CPU 上,它產(chǎn)生的停頓時(shí)間要短于串行回收器,而在單 CPU 或者并發(fā)能力較弱的系統中,并行回收器的效果不會(huì )比串行回收器好,由于多線(xiàn)程的壓力,它的實(shí)際表現很可能比串行回收器差。

開(kāi)啟并行回收器可以使用參數-XX: UseParNewGC,該參數設置新生代使用并行收集器,老年代使用串行收集器。

清單 5. 設置參數-XX: UseParNewGC 的輸出日志
1
2
3
4
5
6
7
8
9
10
11
12
13
[GC [ParNew: 825K->161K(4928K), 0.0155258 secs][Tenured: 8704K->661K(10944K),
  0.0071964 secs] 9017K->661K(15872K),
  [Perm : 2049K->2049K(12288K)], 0.0228090 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
Heap
 par new generation total 4992K, used 179K [0x0f010000, 0x0f570000, 0x14560000)
 eden space 4480K, 4% used [0x0f010000, 0x0f03cda8, 0x0f470000)
 from space 512K, 0% used [0x0f470000, 0x0f470000, 0x0f4f0000)
 to space 512K, 0% used [0x0f4f0000, 0x0f4f0000, 0x0f570000)
 tenured generation total 10944K, used 8853K [0x14560000, 0x15010000, 0x1f010000)
 the space 10944K, 80% used [0x14560000, 0x14e057c0, 0x14e05800, 0x15010000)
 compacting perm gen total 12288K, used 2060K [0x1f010000, 0x1fc10000, 0x23010000)
 the space 12288K, 16% used [0x1f010000, 0x1f213228, 0x1f213400, 0x1fc10000)
No shared spaces configured.

設置參數-XX: UseConcMarkSweepGC 可以要求新生代使用并行收集器,老年代使用 CMS。

清單 6. 設置參數-XX: UseConcMarkSweepGC 的輸出日志
1
2
3
4
5
6
7
8
9
[GC [ParNew: 8967K->669K(14784K), 0.0040895 secs] 8967K->669K(63936K),
  0.0043255 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
 par new generation total 14784K, used 9389K [0x03f50000, 0x04f50000, 0x04f50000)
 eden space 13184K, 66% used [0x03f50000, 0x047d3e58, 0x04c30000)
 from space 1600K, 41% used [0x04dc0000, 0x04e67738, 0x04f50000)
 to space 1600K, 0% used [0x04c30000, 0x04c30000, 0x04dc0000)
 concurrent mark-sweep generation total 49152K, used 0K [0x04f50000, 0x07f50000, 0x09f50000)
 concurrent-mark-sweep perm gen total 12288K, used 2060K [0x09f50000, 0x0ab50000, 0x0df50000)

并行收集器工作時(shí)的線(xiàn)程數量可以使用-XX:ParallelGCThreads 參數指定。一般,最好與 CPU 數量相當,避免過(guò)多的線(xiàn)程數影響垃圾收集性能。在默認情況下,當 CPU 數量小于 8 個(gè),ParallelGCThreads 的值等于 CPU 數量,大于 8 個(gè),ParallelGCThreads 的值等于 3 [5*CPU_Count]/8]。以下測試顯示了筆者筆記本上運行 8 個(gè)線(xiàn)程時(shí)耗時(shí)最短,本人筆記本是 8 核 IntelCPU。

清單 7. 設置為 8 個(gè)線(xiàn)程后 GC 輸出
1
2
3
4
5
6
7
8
9
[GC [ParNew: 8967K->676K(14784K), 0.0036983 secs] 8967K->676K(63936K),
  0.0037662 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
 par new generation total 14784K, used 9395K [0x040e0000, 0x050e0000, 0x050e0000)
 eden space 13184K, 66% used [0x040e0000, 0x04963e58, 0x04dc0000)
 from space 1600K, 42% used [0x04f50000, 0x04ff9100, 0x050e0000)
 to space 1600K, 0% used [0x04dc0000, 0x04dc0000, 0x04f50000)
 concurrent mark-sweep generation total 49152K, used 0K [0x050e0000, 0x080e0000, 0x0a0e0000)
 concurrent-mark-sweep perm gen total 12288K, used 2060K [0x0a0e0000, 0x0ace0000, 0x0e0e0000)
清單 8. 設置為 128 個(gè)線(xiàn)程后 GC 輸出
1
2
[GC [ParNew: 8967K->664K(14784K), 0.0207327 secs] 8967K->664K(63936K),
 0.0208077 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
清單 9. 設置為 640 個(gè)線(xiàn)程后 GC 輸出
1
2
[GC [ParNew: 8967K->667K(14784K), 0.2323704 secs] 8967K->667K(63936K),
 0.2324778 secs] [Times: user=0.34 sys=0.02, real=0.23 secs]
清單 10. 設置為 1280 個(gè)線(xiàn)程后 GC 輸出
1
2
Error occurred during initialization of VM
Too small new size specified
  • 新生代并行回收 (Parallel Scavenge) 收集器

新生代并行回收收集器也是使用復制算法的收集器。從表面上看,它和并行收集器一樣都是多線(xiàn)程、獨占式的收集器。但是,并行回收收集器有一個(gè)重要的特點(diǎn):它非常關(guān)注系統的吞吐量。

新生代并行回收收集器可以使用以下參數啟用:

-XX: UseParallelGC:新生代使用并行回收收集器,老年代使用串行收集器。

-XX: UseParallelOldGC:新生代和老年代都是用并行回收收集器。

清單 11. 設置為 24 個(gè)線(xiàn)程后 GC 輸出
1
2
3
4
5
6
7
8
9
Heap
 PSYoungGen total 4800K, used 893K [0x1dac0000, 0x1e010000, 0x23010000)
 eden space 4160K, 21% used [0x1dac0000,0x1db9f570,0x1ded0000)
 from space 640K, 0% used [0x1df70000,0x1df70000,0x1e010000)
 to space 640K, 0% used [0x1ded0000,0x1ded0000,0x1df70000)
 ParOldGen total 19200K, used 16384K [0x13010000, 0x142d0000, 0x1dac0000)
 object space 19200K, 85% used [0x13010000,0x14010020,0x142d0000)
 PSPermGen total 12288K, used 2054K [0x0f010000, 0x0fc10000, 0x13010000)
 object space 12288K, 16% used [0x0f010000,0x0f2119c0,0x0fc10000)

新生代并行回收收集器可以使用以下參數啟用:

-XX: MaxGCPauseMills:設置最大垃圾收集停頓時(shí)間,它的值是一個(gè)大于 0 的整數。收集器在工作時(shí)會(huì )調整 Java 堆大小或者其他一些參數,盡可能地把停頓時(shí)間控制在 MaxGCPauseMills 以?xún)?。如果希望減少停頓時(shí)間,而把這個(gè)值設置得很小,為了達到預期的停頓時(shí)間,JVM 可能會(huì )使用一個(gè)較小的堆 (一個(gè)小堆比一個(gè)大堆回收快),而這將導致垃圾回收變得很頻繁,從而增加了垃圾回收總時(shí)間,降低了吞吐量。

-XX: GCTimeRatio:設置吞吐量大小,它的值是一個(gè) 0-100 之間的整數。假設 GCTimeRatio 的值為 n,那么系統將花費不超過(guò) 1/(1 n) 的時(shí)間用于垃圾收集。比如 GCTimeRatio 等于 19,則系統用于垃圾收集的時(shí)間不超過(guò) 1/(1 19)=5%。默認情況下,它的取值是 99,即不超過(guò) 1%的時(shí)間用于垃圾收集。

除此之外,并行回收收集器與并行收集器另一個(gè)不同之處在于,它支持一種自適應的 GC 調節策略,使用-XX: UseAdaptiveSizePolicy 可以打開(kāi)自適應 GC 策略。在這種模式下,新生代的大小、eden 和 survivor 的比例、晉升老年代的對象年齡等參數會(huì )被自動(dòng)調整,以達到在堆大小、吞吐量和停頓時(shí)間之間的平衡點(diǎn)。在手工調優(yōu)比較困難的場(chǎng)合,可以直接使用這種自適應的方式,僅指定虛擬機的最大堆、目標的吞吐量 (GCTimeRatio) 和停頓時(shí)間 (MaxGCPauseMills),讓虛擬機自己完成調優(yōu)工作。

清單 12. 新生代并行回收收集器 GC 輸出
1
2
3
4
5
6
7
8
9
Heap
 PSYoungGen total 4800K, used 893K [0x1dac0000, 0x1e010000, 0x23010000)
 eden space 4160K, 21% used [0x1dac0000,0x1db9f570,0x1ded0000)
 from space 640K, 0% used [0x1df70000,0x1df70000,0x1e010000)
 to space 640K, 0% used [0x1ded0000,0x1ded0000,0x1df70000)
 PSOldGen total 19200K, used 16384K [0x13010000, 0x142d0000, 0x1dac0000)
 object space 19200K, 85% used [0x13010000,0x14010020,0x142d0000)
 PSPermGen total 12288K, used 2054K [0x0f010000, 0x0fc10000, 0x13010000)
 object space 12288K, 16% used [0x0f010000,0x0f2119c0,0x0fc10000)

它也顯示了收集器的工作成果,也就是回收前的內存大小和回收后的內存大小,以及花費的時(shí)間。

  • 老年代并行回收收集器

老年代的并行回收收集器也是一種多線(xiàn)程并發(fā)的收集器。和新生代并行回收收集器一樣,它也是一種關(guān)注吞吐量的收集器。老年代并行回收收集器使用標記-壓縮算法,JDK1.6 之后開(kāi)始啟用。

使用-XX: UseParallelOldGC 可以在新生代和老生代都使用并行回收收集器,這是一對非常關(guān)注吞吐量的垃圾收集器組合,在對吞吐量敏感的系統中,可以考慮使用。參數-XX:ParallelGCThreads 也可以用于設置垃圾回收時(shí)的線(xiàn)程數量。

清單 13 是設置線(xiàn)程數量為 100 時(shí)老年代并行回收收集器輸出日志:

清單 13. 老年代并行回收收集器設置 100 線(xiàn)程時(shí) GC 輸出
1
2
3
4
5
6
7
8
9
Heap
 PSYoungGen total 4800K, used 893K [0x1dac0000, 0x1e010000, 0x23010000)
 eden space 4160K, 21% used [0x1dac0000,0x1db9f570,0x1ded0000)
 from space 640K, 0% used [0x1df70000,0x1df70000,0x1e010000)
 to space 640K, 0% used [0x1ded0000,0x1ded0000,0x1df70000)
 ParOldGen total 19200K, used 16384K [0x13010000, 0x142d0000, 0x1dac0000)
 object space 19200K, 85% used [0x13010000,0x14010020,0x142d0000)
 PSPermGen total 12288K, used 2054K [0x0f010000, 0x0fc10000, 0x13010000)
 object space 12288K, 16% used [0x0f010000,0x0f2119c0,0x0fc10000)
  • CMS 收集器

與并行回收收集器不同,CMS 收集器主要關(guān)注于系統停頓時(shí)間。CMS 是 Concurrent Mark Sweep 的縮寫(xiě),意為并發(fā)標記清除,從名稱(chēng)上可以得知,它使用的是標記-清除算法,同時(shí)它又是一個(gè)使用多線(xiàn)程并發(fā)回收的垃圾收集器。

CMS 工作時(shí),主要步驟有:初始標記、并發(fā)標記、重新標記、并發(fā)清除和并發(fā)重置。其中初始標記和重新標記是獨占系統資源的,而并發(fā)標記、并發(fā)清除和并發(fā)重置是可以和用戶(hù)線(xiàn)程一起執行的。因此,從整體上來(lái)說(shuō),CMS 收集不是獨占式的,它可以在應用程序運行過(guò)程中進(jìn)行垃圾回收。

根據標記-清除算法,初始標記、并發(fā)標記和重新標記都是為了標記出需要回收的對象。并發(fā)清理則是在標記完成后,正式回收垃圾對象;并發(fā)重置是指在垃圾回收完成后,重新初始化 CMS 數據結構和數據,為下一次垃圾回收做好準備。并發(fā)標記、并發(fā)清理和并發(fā)重置都是可以和應用程序線(xiàn)程一起執行的。

CMS 收集器在其主要的工作階段雖然沒(méi)有暴力地徹底暫停應用程序線(xiàn)程,但是由于它和應用程序線(xiàn)程并發(fā)執行,相互搶占 CPU,所以在 CMS 執行期內對應用程序吞吐量造成一定影響。CMS 默認啟動(dòng)的線(xiàn)程數是 (ParallelGCThreads 3)/4),ParallelGCThreads 是新生代并行收集器的線(xiàn)程數,也可以通過(guò)-XX:ParallelCMSThreads 參數手工設定 CMS 的線(xiàn)程數量。當 CPU 資源比較緊張時(shí),受到 CMS 收集器線(xiàn)程的影響,應用程序的性能在垃圾回收階段可能會(huì )非常糟糕。

由于 CMS 收集器不是獨占式的回收器,在 CMS 回收過(guò)程中,應用程序仍然在不停地工作。在應用程序工作過(guò)程中,又會(huì )不斷地產(chǎn)生垃圾。這些新生成的垃圾在當前 CMS 回收過(guò)程中是無(wú)法清除的。同時(shí),因為應用程序沒(méi)有中斷,所以在 CMS 回收過(guò)程中,還應該確保應用程序有足夠的內存可用。因此,CMS 收集器不會(huì )等待堆內存飽和時(shí)才進(jìn)行垃圾回收,而是當前堆內存使用率達到某一閾值時(shí),便開(kāi)始進(jìn)行回收,以確保應用程序在 CMS 工作過(guò)程中依然有足夠的空間支持應用程序運行。

這個(gè)回收閾值可以使用-XX:CMSInitiatingOccupancyFraction 來(lái)指定,默認是 68。即當老年代的空間使用率達到 68%時(shí),會(huì )執行一次 CMS 回收。如果應用程序的內存使用率增長(cháng)很快,在 CMS 的執行過(guò)程中,已經(jīng)出現了內存不足的情況,此時(shí),CMS 回收將會(huì )失敗,JVM 將啟動(dòng)老年代串行收集器進(jìn)行垃圾回收。如果這樣,應用程序將完全中斷,直到垃圾收集完成,這時(shí),應用程序的停頓時(shí)間可能很長(cháng)。因此,根據應用程序的特點(diǎn),可以對-XX:CMSInitiatingOccupancyFraction 進(jìn)行調優(yōu)。如果內存增長(cháng)緩慢,則可以設置一個(gè)稍大的值,大的閾值可以有效降低 CMS 的觸發(fā)頻率,減少老年代回收的次數可以較為明顯地改善應用程序性能。反之,如果應用程序內存使用率增長(cháng)很快,則應該降低這個(gè)閾值,以避免頻繁觸發(fā)老年代串行收集器。

標記-清除算法將會(huì )造成大量?jì)却嫠槠?,離散的可用空間無(wú)法分配較大的對象。在這種情況下,即使堆內存仍然有較大的剩余空間,也可能會(huì )被迫進(jìn)行一次垃圾回收,以換取一塊可用的連續內存,這種現象對系統性能是相當不利的,為了解決這個(gè)問(wèn)題,CMS 收集器還提供了幾個(gè)用于內存壓縮整理的算法。

-XX: UseCMSCompactAtFullCollection 參數可以使 CMS 在垃圾收集完成后,進(jìn)行一次內存碎片整理。內存碎片的整理并不是并發(fā)進(jìn)行的。-XX:CMSFullGCsBeforeCompaction 參數可以用于設定進(jìn)行多少次 CMS 回收后,進(jìn)行一次內存壓縮。

-XX:CMSInitiatingOccupancyFraction 設置為 100,同時(shí)設置-XX: UseCMSCompactAtFullCollection 和-XX:CMSFullGCsBeforeCompaction,日志輸出如下:

清單 14.CMS 垃圾回收器 GC 輸出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[GC [DefNew: 825K->149K(4928K), 0.0023384 secs][Tenured: 8704K->661K(10944K),
  0.0587725 secs] 9017K->661K(15872K),
  [Perm : 374K->374K(12288K)], 0.0612037 secs] [Times: user=0.01 sys=0.02, real=0.06 secs]
Heap
 def new generation total 4992K, used 179K [0x27010000, 0x27570000, 0x2c560000)
 eden space 4480K, 4% used [0x27010000, 0x2703cda8, 0x27470000)
 from space 512K, 0% used [0x27470000, 0x27470000, 0x274f0000)
 to space 512K, 0% used [0x274f0000, 0x274f0000, 0x27570000)
 tenured generation total 10944K, used 8853K [0x2c560000, 0x2d010000, 0x37010000)
 the space 10944K, 80% used [0x2c560000, 0x2ce057c8, 0x2ce05800, 0x2d010000)
 compacting perm gen total 12288K, used 374K [0x37010000, 0x37c10000, 0x3b010000)
 the space 12288K, 3% used [0x37010000, 0x3706db10, 0x3706dc00, 0x37c10000)
 ro space 10240K, 51% used [0x3b010000, 0x3b543000, 0x3b543000, 0x3ba10000)
 rw space 12288K, 55% used [0x3ba10000, 0x3c0ae4f8, 0x3c0ae600, 0x3c610000)
  • G1 收集器 (Garbage First)

G1 收集器的目標是作為一款服務(wù)器的垃圾收集器,因此,它在吞吐量和停頓控制上,預期要優(yōu)于 CMS 收集器。

與 CMS 收集器相比,G1 收集器是基于標記-壓縮算法的。因此,它不會(huì )產(chǎn)生空間碎片,也沒(méi)有必要在收集完成后,進(jìn)行一次獨占式的碎片整理工作。G1 收集器還可以進(jìn)行非常精確的停頓控制。它可以讓開(kāi)發(fā)人員指定當停頓時(shí)長(cháng)為 M 時(shí),垃圾回收時(shí)間不超過(guò) N。使用參數-XX: UnlockExperimentalVMOptions –XX: UseG1GC 來(lái)啟用 G1 回收器,設置 G1 回收器的目標停頓時(shí)間:-XX:MaxGCPauseMills=20,-XX:GCPauseIntervalMills=200。

收集器對系統性能的影響

通過(guò)清單 15 所示代碼運行 1 萬(wàn)次循環(huán),每次分配 512*100B 空間,采用不同的垃圾回收器,輸出程序運行所消耗的時(shí)間。

清單 15. 性能測試代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.HashMap;
public class GCTimeTest {
 static HashMap map = new HashMap();
  
 public static void main(String[] args){
 long begintime = System.currentTimeMillis();
 for(int i=0;i<10000;i ){
 if(map.size()*512/1024/1024>=400){
 map.clear();//保護內存不溢出
 System.out.println('clean map');
 }
 byte[] b1;
 for(int j=0;j<100;j ){
 b1 = new byte[512];
 map.put(System.nanoTime(), b1);//不斷消耗內存
 }
 }
 long endtime = System.currentTimeMillis();
 System.out.println(endtime-begintime);
 }
}

使用參數-Xmx512M -Xms512M -XX: UseParNewGC 運行代碼,輸出如下:

clean map 8565

cost time=1655

使用參數-Xmx512M -Xms512M -XX: UseParallelOldGC –XX:ParallelGCThreads=8 運行代碼,輸出如下:

clean map 8798

cost time=1998

使用參數-Xmx512M -Xms512M -XX: UseSerialGC 運行代碼,輸出如下:

clean map 8864

cost time=1717

使用參數-Xmx512M -Xms512M -XX: UseConcMarkSweepGC 運行代碼,輸出如下:

clean map 8862

cost time=1530

上面例子的 GC 輸出可以看出,采用不同的垃圾回收機制及設定不同的線(xiàn)程數,對于代碼段的整體執行時(shí)間有較大的影響。需要讀者有針對性地選用適合自己代碼段的垃圾回收機制。

GC 相關(guān)參數總結

1. 與串行回收器相關(guān)的參數

-XX: UseSerialGC:在新生代和老年代使用串行回收器。

-XX: SuivivorRatio:設置 eden 區大小和 survivor 區大小的比例。

-XX: PretenureSizeThreshold:設置大對象直接進(jìn)入老年代的閾值。當對象的大小超過(guò)這個(gè)值時(shí),將直接在老年代分配。

-XX:MaxTenuringThreshold:設置對象進(jìn)入老年代的年齡的最大值。每一次 Minor GC 后,對象年齡就加 1。任何大于這個(gè)年齡的對象,一定會(huì )進(jìn)入老年代。

2. 與并行 GC 相關(guān)的參數

-XX: UseParNewGC: 在新生代使用并行收集器。

-XX: UseParallelOldGC: 老年代使用并行回收收集器。

-XX:ParallelGCThreads:設置用于垃圾回收的線(xiàn)程數。通常情況下可以和 CPU 數量相等。但在 CPU 數量比較多的情況下,設置相對較小的數值也是合理的。

-XX:MaxGCPauseMills:設置最大垃圾收集停頓時(shí)間。它的值是一個(gè)大于 0 的整數。收集器在工作時(shí),會(huì )調整 Java 堆大小或者其他一些參數,盡可能地把停頓時(shí)間控制在 MaxGCPauseMills 以?xún)取?/p>

-XX:GCTimeRatio:設置吞吐量大小,它的值是一個(gè) 0-100 之間的整數。假設 GCTimeRatio 的值為 n,那么系統將花費不超過(guò) 1/(1 n) 的時(shí)間用于垃圾收集。

-XX: UseAdaptiveSizePolicy:打開(kāi)自適應 GC 策略。在這種模式下,新生代的大小,eden 和 survivor 的比例、晉升老年代的對象年齡等參數會(huì )被自動(dòng)調整,以達到在堆大小、吞吐量和停頓時(shí)間之間的平衡點(diǎn)。

3. 與 CMS 回收器相關(guān)的參數

-XX: UseConcMarkSweepGC: 新生代使用并行收集器,老年代使用 CMS 串行收集器。

-XX: ParallelCMSThreads: 設定 CMS 的線(xiàn)程數量。

-XX: CMSInitiatingOccupancyFraction:設置 CMS 收集器在老年代空間被使用多少后觸發(fā),默認為 68%。

-XX: UseFullGCsBeforeCompaction:設定進(jìn)行多少次 CMS 垃圾回收后,進(jìn)行一次內存壓縮。

-XX: CMSClassUnloadingEnabled:允許對類(lèi)元數據進(jìn)行回收。

-XX: CMSParallelRemarkEndable:啟用并行重標記。

-XX:CMSInitatingPermOccupancyFraction:當永久區占用率達到這一百分比后,啟動(dòng) CMS 回收 (前提是-XX: CMSClassUnloadingEnabled 激活了)。

-XX:UseCMSInitatingOccupancyOnly:表示只在到達閾值的時(shí)候,才進(jìn)行 CMS 回收。

-XX: CMSIncrementalMode:使用增量模式,比較適合單 CPU。

4. 與 G1 回收器相關(guān)的參數

-XX: UseG1GC:使用 G1 回收器。

-XX: UnlockExperimentalVMOptions:允許使用實(shí)驗性參數。

-XX: MaxGCPauseMills:設置最大垃圾收集停頓時(shí)間。

-XX: GCPauseIntervalMills:設置停頓間隔時(shí)間。

5. 其他參數

-XX: DisableExplicitGC: 禁用顯示 GC。

結束語(yǔ)

通過(guò)本文的學(xué)習,讀者可以掌握基本的 JVM 垃圾回收器設計原理及使用規范?;诠P者多年的工作經(jīng)驗,沒(méi)有哪一條優(yōu)化是可以照本宣科的,它一定是基于您對 JVM 垃圾回收器工作原理及自身程序設計有一定了解前提下,通過(guò)大量的實(shí)驗來(lái)找出最適合自己的優(yōu)化方案。


    本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
    打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
    猜你喜歡
    類(lèi)似文章
    如何調優(yōu)JVM
    JVM有幾種垃圾回收(GC)算法,你知道嗎?
    【JVM】HotSpot JVM內存管理和GC策略總結
    Java虛擬機詳解05
    7種jvm垃圾回收器,這次全部搞懂
    Java SE 6 Hotspot 虛擬機垃圾回收調優(yōu)
    更多類(lèi)似文章 >>
    生活服務(wù)
    分享 收藏 導長(cháng)圖 關(guān)注 下載文章
    綁定賬號成功
    后續可登錄賬號暢享VIP特權!
    如果VIP功能使用有故障,
    可點(diǎn)擊這里聯(lián)系客服!

    聯(lián)系客服

    欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久