成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java內(nèi)存與垃圾回收調(diào)優(yōu)

開發(fā) 后端
要了解Java垃圾收集機制,先理解JVM內(nèi)存模式是非常重要的。今天我們將會了解JVM內(nèi)存的各個部分、如何監(jiān)控以及垃圾收集調(diào)優(yōu)。

要了解Java垃圾收集機制,先理解JVM內(nèi)存模式是非常重要的。今天我們將會了解JVM內(nèi)存的各個部分、如何監(jiān)控以及垃圾收集調(diào)優(yōu)。

Java(JVM)內(nèi)存模型

正如你從上面的圖片看到的,JVM內(nèi)存被分成多個獨立的部分。廣泛地說,JVM堆內(nèi)存被分為兩部分——年輕代(Young Generation)和老年代(Old Generation)。

年輕代

年輕代是所有新對象產(chǎn)生的地方。當年輕代內(nèi)存空間被用完時,就會觸發(fā)垃圾回收。這個垃圾回收叫做Minor GC。年輕代被分為3個部分——Enden區(qū)和兩個Survivor區(qū)。

年輕代空間的要點:

  • 大多數(shù)新建的對象都位于Eden區(qū)。
  • 當Eden區(qū)被對象填滿時,就會執(zhí)行Minor GC。并把所有存活下來的對象轉(zhuǎn)移到其中一個survivor區(qū)。
  • Minor GC同樣會檢查存活下來的對象,并把它們轉(zhuǎn)移到另一個survivor區(qū)。這樣在一段時間內(nèi),總會有一個空的survivor區(qū)。
  • 經(jīng)過多次GC周期后,仍然存活下來的對象會被轉(zhuǎn)移到年老代內(nèi)存空間。通常這是在年輕代有資格提升到年老代前通過設(shè)定年齡閾值來完成的。

年老代

年老代內(nèi)存里包含了長期存活的對象和經(jīng)過多次Minor GC后依然存活下來的對象。通常會在老年代內(nèi)存被占滿時進行垃圾回收。老年代的垃圾收集叫做Major GC。Major GC會花費更多的時間。

Stop the World事件

所有的垃圾收集都是“Stop the World”事件,因為所有的應用線程都會停下來直到操作完成(所以叫“Stop the World”)。

因為年輕代里的對象都是一些臨時(short-lived )對象,執(zhí)行Minor GC非常快,所以應用不會受到(“Stop the World”)影響。

由于Major GC會檢查所有存活的對象,因此會花費更長的時間。應該盡量減少Major GC。因為Major GC會在垃圾回收期間讓你的應用反應遲鈍,所以如果你有一個需要快速響應的應用發(fā)生多次Major GC,你會看到超時錯誤。

垃圾回收時間取決于垃圾回收策略。這就是為什么有必要去監(jiān)控垃圾收集和對垃圾收集進行調(diào)優(yōu)。從而避免要求快速響應的應用出現(xiàn)超時錯誤。

***代

***代或者“Perm Gen”包含了JVM需要的應用元數(shù)據(jù),這些元數(shù)據(jù)描述了在應用里使用的類和方法。注意,***代不是Java堆內(nèi)存的一部分。

***代存放JVM運行時使用的類。***代同樣包含了Java SE庫的類和方法。***代的對象在full GC時進行垃圾收集。

方法區(qū)

方法區(qū)是***代空間的一部分,并用來存儲類型信息(運行時常量和靜態(tài)變量)和方法代碼和構(gòu)造函數(shù)代碼。

內(nèi)存池

如果JVM實現(xiàn)支持,JVM內(nèi)存管理會為創(chuàng)建內(nèi)存池,用來為不變對象創(chuàng)建對象池。字符串池就是內(nèi)存池類型的一個很好的例子。內(nèi)存池可以屬于堆或者***代,這取決于JVM內(nèi)存管理的實現(xiàn)。

運行時常量池

運行時常量池是每個類常量池的運行時代表。它包含了類的運行時常量和靜態(tài)方法。運行時常量池是方法區(qū)的一部分。

Java棧內(nèi)存

Java棧內(nèi)存用于運行線程。它們包含了方法里的臨時數(shù)據(jù)、堆里其它對象引用的特定數(shù)據(jù)。你可以閱讀棧內(nèi)存和堆內(nèi)存的區(qū)別

Java 堆內(nèi)存開關(guān)

Java提供了大量的內(nèi)存開關(guān)(參數(shù)),我們可以用它來設(shè)置內(nèi)存大小和它們的比例。下面是一些常用的開關(guān):

 

VM 開關(guān) VM 開關(guān)描述
-Xms 設(shè)置JVM啟動時堆的初始化大小。
-Xmx 設(shè)置堆***值。
-Xmn 設(shè)置年輕代的空間大小,剩下的為老年代的空間大小。
-XX:PermGen 設(shè)置***代內(nèi)存的初始化大小。
-XX:MaxPermGen 設(shè)置***代的***值。
-XX:SurvivorRatio 提供Eden區(qū)和survivor區(qū)的空間比例。比如,如果年輕代的大小為10m并且VM開關(guān)是-XX:SurvivorRatio=2,那么將會保留5m內(nèi)存給Eden區(qū)和每個Survivor區(qū)分配2.5m內(nèi)存。默認比例是8。
-XX:NewRatio 提供年老代和年輕代的比例大小。默認值是2。

Java垃圾回收大多數(shù)時候,上面的選項已經(jīng)足夠使用了。但是如果你還想了解其他的選項,那么請查看JVM選項官方網(wǎng)頁

Java垃圾回收會找出沒用的對象,把它從內(nèi)存中移除并釋放出內(nèi)存給以后創(chuàng)建的對象使用。Java程序語言中的一個***優(yōu)點是自動垃圾回收,不像其他的程序語言那樣需要手動分配和釋放內(nèi)存,比如C語言。

垃圾收集器是一個后臺運行程序。它管理著內(nèi)存中的所有對象并找出沒被引用的對象。所有的這些未引用的對象都會被刪除,回收它們的空間并分配給其他對象。

一個基本的垃圾回收過程涉及三個步驟:

  1. 標記:這是***步。在這一步,垃圾收集器會找出哪些對象正在使用和哪些對象不在使用。
  2. 正常清除:垃圾收集器清會除不在使用的對象,回收它們的空間分配給其他對象。
  3. 壓縮清除:為了提升性能,壓縮清除會在刪除沒用的對象后,把所有存活的對象移到一起。這樣可以提高分配新對象的效率。

簡單標記和清除方法存在兩個問題:

  1. 效率很低。因為大多數(shù)新建對象都會成為“沒用對象”。
  2. 經(jīng)過多次垃圾回收周期的對象很有可能在以后的周期也會存活下來。

上面簡單清除方法的問題在于Java垃圾收集的分代回收的,而且在堆內(nèi)存里有年輕代和年老代兩個區(qū)域。我已經(jīng)在上面解釋了Minor GC和Major GC是怎樣掃描對象,以及如何把對象從一個分代空間移到另外一個分代空間。

Java垃圾回收類型

這里有五種可以在應用里使用的垃圾回收類型。僅需要使用JVM開關(guān)就可以在我們的應用里啟用垃圾回收策略。讓我們一起來逐一了解:

  1. Serial GC(-XX:+UseSerialGC):Serial GC使用簡單的標記、清除、壓縮方法對年輕代和年老代進行垃圾回收,即Minor GC和Major GC。Serial GC在client模式(客戶端模式)很有用,比如在簡單的獨立應用和CPU配置較低的機器。這個模式對占有內(nèi)存較少的應用很管用。
  2. Parallel GC(-XX:+UseParallelGC):除了會產(chǎn)生N個線程來進行年輕代的垃圾收集外,Parallel GC和Serial GC幾乎一樣。這里的N是系統(tǒng)CPU的核數(shù)。我們可以使用 -XX:ParallelGCThreads=n 這個JVM選項來控制線程數(shù)量。并行垃圾收集器也叫throughput收集器。因為它使用了多CPU加快垃圾回收性能。Parallel GC在進行年老代垃圾收集時使用單線程。
  3. Parallel Old GC(-XX:+UseParallelOldGC):和Parallel GC一樣。不同之處,Parallel Old GC在年輕代垃圾收集和年老代垃圾回收時都使用多線程收集。
  4. 并發(fā)標記清除(CMS)收集器(-XX:+UseConcMarkSweepGC):CMS收集器也被稱為短暫停頓并發(fā)收集器。它是對年老代進行垃圾收集的。CMS收集器通過多線程并發(fā)進行垃圾回收,盡量減少垃圾收集造成的停頓。CMS收集器對年輕代進行垃圾回收使用的算法和Parallel收集器一樣。這個垃圾收集器適用于不能忍受長時間停頓要求快速響應的應用。可使用 -XX:ParallelCMSThreads=n JVM選項來限制CMS收集器的線程數(shù)量。
  5. G1垃圾收集器(-XX:+UseG1GC) G1(Garbage First):垃圾收集器是在Java 7后才可以使用的特性,它的長遠目標時代替CMS收集器。G1收集器是一個并行的、并發(fā)的和增量式壓縮短暫停頓的垃圾收集器。G1收集器和其他的收集器運行方式不一樣,不區(qū)分年輕代和年老代空間。它把堆空間劃分為多個大小相等的區(qū)域。當進行垃圾收集時,它會優(yōu)先收集存活對象較少的區(qū)域,因此叫“Garbage First”。你可以在Oracle Garbage-FIrst收集器文檔找到更多詳細信息。

Java垃圾收集監(jiān)控

我們可以使用命令行和圖形工具來監(jiān)控監(jiān)控應用垃圾回收。例如,我使用Java SE下載頁中的一個demo來實驗。

如果你想使用同樣的應用,可以到Java SE下載頁面下載JDK 7和JavaFX演示和示例。我使用的示例應用是Java2Demo.jar,它位于 jdk1.7.0_55/demo/jfc/Java2D 目錄下。這只是一個可選步驟,你可以運行GC監(jiān)控命令監(jiān)控任何Java應用。

我打開演示應用使用的命令是:

  1. pankaj@Pankaj:~/Downloads/jdk1.7.0_55/demo/jfc/Java2D$ java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar 

jsat

可以使用jstat命令行工具監(jiān)控JVM內(nèi)存和垃圾回收。標準的JDK已經(jīng)附帶了jstat,所以不需要做任何額外的事情就可以得到它。

要運行jstat你需要知道應用的進程id,你可以使用 ps -eaf | grep java 命令獲取進程id。

  1. pankaj@Pankaj:~$ ps -eaf | grep Java2Demo.jar 
  2. 501 9582 11579 0 9:48PM ttys000 0:21.66 /usr/bin/java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseG1GC -jar Java2Demo.jar 
  3. 501 14073 14045 0 9:48PM ttys002 0:00.00 grep Java2Demo.jar 

從上面知道,我的Java應用進程id是9582。現(xiàn)在可以運行jstat命令了,就像下面展示的一樣:

  1. pankaj@Pankaj:~$ jstat -gc 9582 1000 
  2. S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 
  3. 1024.0 1024.0 0.0 0.0 8192.0 7933.3 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 
  4. 1024.0 1024.0 0.0 0.0 8192.0 8026.5 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 
  5. 1024.0 1024.0 0.0 0.0 8192.0 8030.0 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 
  6. 1024.0 1024.0 0.0 0.0 8192.0 8122.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 
  7. 1024.0 1024.0 0.0 0.0 8192.0 8171.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 
  8. 1024.0 1024.0 48.7 0.0 8192.0 106.7 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656 
  9. 1024.0 1024.0 48.7 0.0 8192.0 145.8 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656 

jstat命令的***一個參數(shù)是每個輸出的時間間隔。每隔一秒就會打印出內(nèi)存和垃圾收集數(shù)據(jù)。

讓我們一起來對每一列的意義進行逐一了解:

  • S0C和S1C:這一列展示了Survivor0和Survivor1區(qū)的當前大小(單位KB)。
  • S0U和S1U:這一列展示了當前Survivor0和Survivor1區(qū)的使用情況(單位KB)。注意:無論任何時候,總會有一個Survivor區(qū)是空著的。
  • EC和EU:這些列展示了Eden區(qū)當前空間大小和使用情況(單位KB)。注意:EU的大小一直在增大。而且只要大小接近EC時,就會觸發(fā)Minor GC并且EU將會減小。
  • OC和OU:這些列展示了年老代當前空間大小和當前使用情況(單位KB)。
  • PC和PU:這些列展示了Perm Gen(***代)當前空間大小和當前使用情況(單位KB)。
  • YGC和YGCT:YGC這列顯示了發(fā)生在年輕代的GC事件的數(shù)量。YGCT這列顯示了在年輕代進行GC操作的累計時間。注意:在EU的值由于minor GC導致下降時,同一行的YGC和YGCT都會增加。
  • FGC和FGCT:FGC列顯示了發(fā)生Full GC事件的次數(shù)。FGCT顯示了進行Full GC操作的累計時間。注意:相對于年輕代的GC使用時間,F(xiàn)ull GC所用的時間長很多。
  • GCT:這一列顯示了GC操作的總累計時間。注意:總累計時間是YGCT和FGCT兩列所用時間的總和(GCT=YGCT+FGCT)。

jstat的優(yōu)點,我們同樣可以在沒有GUI的遠程服務器上運行jstat。注意:我們是通過 -Xmn10m 選項來指定S0C、S1C和EC的總和為10m的。

Java VisualVM及Visual GC插件

如果你想在GUI里查看內(nèi)存和GC,那么可以使用jvisualvm工具。Java VisualVM同樣是JDK的一部分,所以你不需要單獨去下載。

在終端運行jvisualvm命令啟動Java VisualVM程序。一旦啟動程序,你需要從Tools->Plugins選項安裝Visual GC插件,就像下面圖片展示的。

安裝完Visual GC插件后,從左邊欄打開應用并把視角轉(zhuǎn)到Visual GC部分。你將會得到關(guān)于JVM內(nèi)存和垃圾收集詳情,如下圖所示。

Java垃圾回收調(diào)優(yōu)

Java垃圾回收調(diào)優(yōu)應該是提升應用吞吐量的***一個選擇。在你發(fā)現(xiàn)應用由于長時間垃圾回收導致了應用性能下降、出現(xiàn)超時的時候,應該考慮Java垃圾收集調(diào)優(yōu)。

如果你在日志里看到 java.lang.OutOfMemoryError: PermGen space錯誤,那么可以嘗試使用 -XX:PermGen 和 -XX:MaxPermGen JVM選項去監(jiān)控并增加Perm Gen內(nèi)存空間。你也可以嘗試使用-XX:+CMSClassUnloadingEnabled并查看使用CMS垃圾收集器的執(zhí)行性能。

如果你看到了大量的Full GC操作,那么你應該嘗試增大老年代的內(nèi)存空間。

全面垃圾收集調(diào)優(yōu)要花費大量的努力和時間,這里沒有一塵不變的硬性調(diào)優(yōu)規(guī)則。你需要去嘗試不同的選項并且對這些選項進行對比,從而找出最適合自己應用的方案。

這就是所有的Java內(nèi)存模型和垃圾回收內(nèi)容。希望對你理解JVM內(nèi)存和垃圾收集過程有所幫助。

原文鏈接: journaldev 翻譯: ImportNew.com - 進林

譯文鏈接: http://www.importnew.com/14086.html

 

 

責任編輯:張偉 來源: ImportNew
相關(guān)推薦

2015-07-06 10:14:25

Java垃圾回收實戰(zhàn)

2023-11-23 09:26:50

Java調(diào)優(yōu)

2012-01-09 16:53:36

JavaJVM

2012-01-10 11:19:35

JavaJVM

2010-09-26 11:22:22

JVM垃圾回收JVM

2012-01-09 17:06:16

JavaJVM

2012-08-06 09:26:19

Java虛擬機垃圾回收

2021-02-04 10:43:52

開發(fā)技能代碼

2011-08-15 16:28:06

Cocoa內(nèi)存管理

2012-01-10 14:25:36

JavaJVM

2023-12-19 21:52:51

Go垃圾回收開發(fā)

2017-08-04 10:53:30

回收算法JVM垃圾回收器

2009-09-02 09:23:26

.NET內(nèi)存管理機制

2017-02-21 16:40:16

Android垃圾回收內(nèi)存泄露

2020-08-10 17:49:25

JVM內(nèi)存溢出

2021-01-04 10:08:07

垃圾回收Java虛擬機

2023-02-26 11:50:04

Hbase程序Oracle

2017-04-25 14:39:55

JVM內(nèi)存Java

2020-12-10 16:11:17

Java開發(fā)代碼

2010-12-13 11:14:04

Java垃圾回收算法
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 精国产品一区二区三区四季综 | 亚洲精品乱码久久久久久蜜桃91 | 欧美在线视频一区二区 | 黑人巨大精品欧美一区二区一视频 | 91精品国产综合久久香蕉922 | 欧美日韩精品区 | 欧美成人影院在线 | 色婷婷av久久久久久久 | 能看的av | 天天摸天天干 | 午夜视频大全 | 九色在线观看 | 国产视频h| 国产在线精品免费 | 国产精品美女久久久久aⅴ国产馆 | 欧美日日 | 日本免费一区二区三区视频 | 国产一区二区日韩 | 五月婷婷中文 | 亚洲精品av在线 | 999免费视频 | 99热这里| 日韩精品免费视频 | 精品久久精品 | 99精品欧美一区二区蜜桃免费 | 伊人爽| 日韩视频免费 | 欧美日韩在线视频观看 | 中文字幕不卡在线观看 | 精精精精xxxx免费视频 | 二区中文 | 久久精品日产第一区二区三区 | 毛片区| 午夜寂寞影院在线观看 | 亚洲va欧美va人人爽午夜 | 三级av在线 | 欧美a区 | 欧美在线视频一区二区 | 国产一区二区三区色淫影院 | 亚洲精品在线看 | 成人欧美一区二区三区在线播放 |