亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Java 內(nèi)存結(jié)構(gòu)備忘錄

wow_worktile / 3593人閱讀

摘要:本文詳細(xì)描述了堆內(nèi)存模型,垃圾回收算法以及處理內(nèi)存泄露的最佳方案,并輔之以圖表,希望能對(duì)理解內(nèi)存結(jié)構(gòu)有所幫助。該區(qū)域也稱為內(nèi)存模型的本地區(qū)。在中,內(nèi)存泄露是指對(duì)象已不再使用,但垃圾回收未能將他們視做不使用對(duì)象予以回收。

本文詳細(xì)描述了 Java 堆內(nèi)存模型,垃圾回收算法以及處理內(nèi)存泄露的最佳方案,并輔之以圖表,希望能對(duì)理解 Java 內(nèi)存結(jié)構(gòu)有所幫助。原文作者 Sumith Puri,本文系 OneAPM 工程師編譯整理。

下圖展示了 Java 堆內(nèi)存模型,以及運(yùn)行在 Java 虛擬機(jī)中任意 Java 應(yīng)用的 PermGen (內(nèi)存永久保存區(qū)域),下面的比率展示了 JVM 各代類型允許的內(nèi)存大小分配情況,所有的數(shù)據(jù)均適用于 Java 1.7 及以下版本。該圖也被稱為 Java 內(nèi)存模型的“管理區(qū)(Managed Area)”。

Java 內(nèi)存結(jié)構(gòu)(Java 內(nèi)存模型)

除此之外,還有一塊堆棧區(qū)(Stack Area),可通過 -Xss 選項(xiàng)進(jìn)行配置。該區(qū)域存儲(chǔ)了所有線程的堆引用、本地引用、程序計(jì)數(shù)器寄存器、代碼緩存以及本地變量。該區(qū)域也稱為內(nèi)存模型的本地區(qū)(Native Area)。

Java 內(nèi)存模型(結(jié)構(gòu))的管理區(qū) [Young Generation/Nursery] 伊甸園區(qū)(Eden Space)

所有新對(duì)象都首先在 Eden Space 創(chuàng)建。一旦該區(qū)達(dá)到由 JVM 設(shè)定的任意閾值,新生代垃圾回收機(jī)制(Minor GC)就會(huì)啟動(dòng)。它會(huì)首先清除所有的非引用對(duì)象,并將引用對(duì)象從 "eden" 與 "from" 區(qū)移至 "to" 幸存者區(qū)。垃圾回收一結(jié)束,"from" 與 "to" 的角色(名字)就會(huì)對(duì)換。

[Young Generation/Nursery] 幸存者 1 區(qū) (From)

這是幸存者區(qū)的一部分?;蛘咭暈樾掖嬲邊^(qū)中的一個(gè)角色。這兒就是之前垃圾回收中的 "to" 角色。

[Young Generation/Nursery] 幸存者 2 區(qū) (To)

這也是幸存者區(qū)的一部分。也可以視為幸存者區(qū)中的一個(gè)角色。垃圾回收過程中的所有引用對(duì)象都會(huì)從 "from" 與 "eden" 區(qū)移至此處。

[Old Generation] 年老代區(qū)(Tenured)

根據(jù)閾值限定的不同,對(duì)象們會(huì)從 "to" 幸存者區(qū)移至年老代區(qū)。你可以使用 -XX:+PrintTenuringDistribution 檢查閾值,該指令會(huì)按照年齡顯示對(duì)象(占用的字節(jié)空間)。年齡是指對(duì)象在幸存者區(qū)內(nèi)移動(dòng)的次數(shù)。

其他重要的標(biāo)記還有 -XX:InitialTenuringThreshold-XX:MaxTenuringThreshold-XX:TargetSurvivorRatio ,這些標(biāo)記能幫你實(shí)現(xiàn)最佳的年老代區(qū)與幸存者區(qū)使用方案。

通過設(shè)置 -XX:InitialTenuringThreshold-XX:MaxTenuringThreshold,可以指定年齡的最初值與最大值,而幸存者區(qū) (To) 的使用率則由 -XX:+NeverTenure-XX:+AlwaysTenure 決定。前者是指永遠(yuǎn)不將對(duì)象存儲(chǔ)到年老代區(qū),而后者恰恰相反,總是將對(duì)象存儲(chǔ)到年老代區(qū)。

此處進(jìn)行的垃圾回收是年老代垃圾回收(Major GC)。當(dāng)堆空間已滿或者年老代區(qū)占滿時(shí),就會(huì)觸發(fā) Major GC。此時(shí),通常會(huì)由一個(gè)“停止一切(Stop-the-World)”事件或線程執(zhí)行垃圾回收。此外,還有另一種稱為全垃圾回收(Full GC)的垃圾回收機(jī)制,會(huì)涉及諸如永久內(nèi)存區(qū)域。

與整體堆內(nèi)存相關(guān)的另兩個(gè)重要且有趣的標(biāo)記是 -XX:SurvivorRatio-XX:NewRatio,前者指定伊甸園區(qū)相對(duì)幸存者區(qū)的比率,后者指定年老代區(qū)相對(duì)新生代區(qū)的比率。

[Permanent Generation] 永久代區(qū)(Permgen space)

永久代區(qū)(Permgen)用于存儲(chǔ)以下信息:常量池 (內(nèi)存池),字段與方法數(shù)據(jù)及代碼。

垃圾回收算法 串行 GC(Serial GC) (-XX:UseSerialGC): 針對(duì)年輕代與年老代的垃圾回收

該算法使用簡單的“標(biāo)記-清掃-壓縮(mark-sweep-compact)”循環(huán)清理年輕代與年老代,適合內(nèi)存占用較低、CPU 使用量較少的客戶端系統(tǒng)。

并行 GC(Parallel GC) (-XX:UseParallelGC): 針對(duì)年輕代與年老代的垃圾回收

該算法使用 N 個(gè)線程(N 的值可以通過 -XX:ParallelGCThreads=N 設(shè)定,N 同時(shí)代表垃圾回收占用的 CPU 內(nèi)核數(shù))。其中,年輕代垃圾回收會(huì)使用 N 個(gè)線程,而年老代只用一個(gè)線程。

并行 Old GC (-XX:UseParallelOldGC): 針對(duì)年輕代與年老代的垃圾回收

該算法對(duì)年輕代與年老代均使用 N 個(gè)線程,其他方面與并行 GC 完全一致。

并發(fā) Mark and Sweep GC (-XX:ConcMarkSweepGC): 針對(duì)年老代的垃圾回收

顧名思義,CMS GC 會(huì)最小化垃圾回收所需的停頓時(shí)間。該算法最適于創(chuàng)建高響應(yīng)度的應(yīng)用,且只作用于年老代。它會(huì)創(chuàng)建多條垃圾回收的線程,與應(yīng)用線程同時(shí)工作。垃圾回收的線程數(shù)量可以使用 -XX:ParallelCMSThreads=n 標(biāo)記指定。

G1 GC (-XX:UseG1GC): 針對(duì)年輕代與年老代的垃圾回收 (將堆內(nèi)存等分為大小相同的區(qū)塊)

這是一種并行、并發(fā)、不斷壓縮的低停頓垃圾回收器。G1 是在 Java 7 中引入以取代 CMS GC 的,它會(huì)先將堆內(nèi)存分為多個(gè)大小相等的區(qū)塊,繼而執(zhí)行垃圾回收。通常,從活動(dòng)數(shù)據(jù)最少的區(qū)塊開始,因此以垃圾為先。

最常見的內(nèi)存溢出問題

所有 Java 程序員都應(yīng)該知道的最常見的內(nèi)存溢出問題:

Exception in thread "main": java.lang.OutOfMemoryError: Java heap space( Java 堆內(nèi)存)。這并不一定意味著內(nèi)存泄露,也可能是分配的堆內(nèi)存空間太小。此外,在運(yùn)行時(shí)間較長的應(yīng)用中,也可能是因?yàn)橐粋€(gè)無意識(shí)的引用被指向堆對(duì)象(內(nèi)存泄露)。即便是應(yīng)用本身調(diào)用的 APIs,也可能保存著指向無依據(jù)對(duì)象的引用。而且,在大量使用終結(jié)器的應(yīng)用中,對(duì)象們有時(shí)可能正排在終結(jié)隊(duì)列中。當(dāng)這樣的應(yīng)用創(chuàng)建高優(yōu)先級(jí)的線程時(shí),會(huì)導(dǎo)致越來越多的對(duì)象排在終結(jié)隊(duì)列中,最終導(dǎo)致內(nèi)存溢出。

Exception in thread "main": java.lang.OutOfMemoryError: PermGen space(永久存儲(chǔ)空間)。如果加載了很多類與方法,或者創(chuàng)建了很多字符串常量,特別是使用 intern() 方法進(jìn)行創(chuàng)建(從 JDK 7 開始,interned 字符串就不再存儲(chǔ)在 PermGen 中),這類錯(cuò)誤就會(huì)出現(xiàn)。當(dāng)出現(xiàn)這類錯(cuò)誤時(shí),打印的堆棧跟蹤附近可能會(huì)出現(xiàn)如下文本:ClassLoader.defineClass。

Exception in thread "main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit (請求的數(shù)組大小超出 VM 限制)。當(dāng)請求的數(shù)組大小超過可用的堆空間時(shí),這類報(bào)錯(cuò)就會(huì)出現(xiàn)。這類錯(cuò)誤通常歸咎于編程錯(cuò)誤,在運(yùn)行時(shí)請求了極大的數(shù)組大小。

Exception in thread "main": java.lang.OutOfMemoryError:
request bytes for ,交換空間溢出?這是內(nèi)存泄露最常見的根源。通常,當(dāng)操作系統(tǒng)沒有足夠的交換空間,或另一個(gè)進(jìn)程占用了系統(tǒng)中的所有可用內(nèi)存,就會(huì)導(dǎo)致內(nèi)存泄露。簡而言之,由于空間用盡,堆內(nèi)存無法提供所請求的空間大小。該信息中的 "s" 代表失敗的請求所需的內(nèi)存大小(以字節(jié)為單位),而 "r" 代表內(nèi)存請求的原因。在大多數(shù)情況下,此處的 "r" 是報(bào)告分配失敗的源模塊,有時(shí)也會(huì)是具體的原因。

Exception in thread "main": java.lang.OutOfMemoryError: (Native method)(<原因><堆棧跟蹤><本地方法>)。該報(bào)錯(cuò)意味著一個(gè)本地方法遇到內(nèi)存分配失敗。問題的根源在于 Java Native Interface(Java 本地接口) 中存在的錯(cuò)誤,而非 JVM 中運(yùn)行的代碼錯(cuò)誤。若是本地代碼不檢查內(nèi)存分配錯(cuò)誤,應(yīng)由會(huì)直接崩潰,而不會(huì)出現(xiàn)內(nèi)存溢出。

內(nèi)存泄露的定義

你可以將內(nèi)存泄露看做一種疾病,而內(nèi)存溢出錯(cuò)誤為一種征兆。但不是所有的內(nèi)存溢出錯(cuò)誤都意味著內(nèi)存泄露,不是所有的內(nèi)存泄露都以內(nèi)存溢出為征兆。

維基百科的定義:在計(jì)算機(jī)科學(xué)中,內(nèi)存泄露是一種以如下方式發(fā)生的資源泄露——計(jì)算機(jī)程序錯(cuò)誤地分配內(nèi)存,導(dǎo)致不再需要的內(nèi)存得不到釋放。在面向?qū)ο蟮木幊陶Z言中,一個(gè)對(duì)象若存儲(chǔ)在內(nèi)存中,卻無法由運(yùn)行的代碼獲取,即為內(nèi)存泄露。

Java 中常用的內(nèi)存泄露定義

當(dāng)不再需要的對(duì)象引用仍舊多余地予以保存,即為內(nèi)存泄露。

在 Java 中,內(nèi)存泄露是指對(duì)象已不再使用,但垃圾回收未能將他們視做不使用對(duì)象予以回收。

當(dāng)程序不再使用某個(gè)對(duì)象,但在一些無法觸及的位置該對(duì)象仍舊被引用,即為內(nèi)存泄露。也因此,垃圾回收器無法刪除它。該對(duì)象占用的內(nèi)存空間無法釋放,程序所需的總內(nèi)存就會(huì)增加。久而久之,應(yīng)用的性能就會(huì)下降,JVM 可能會(huì)耗盡所有內(nèi)存。

在某種程度上,當(dāng)無法再給年老區(qū)分配內(nèi)存時(shí),內(nèi)存泄露就會(huì)發(fā)生。

內(nèi)存泄露最常見的一些情況:

ThreadLocal 變量

循環(huán)與復(fù)雜的雙向引用

JNI 內(nèi)存泄露

可變的靜態(tài)域(最為常見)

我建議結(jié)合使用 Visual VM 與 JDK,對(duì)內(nèi)存泄露問題進(jìn)行調(diào)試。

常見的內(nèi)存泄露調(diào)試方法

NetBeans 分析器

使用 jhat Utility

創(chuàng)建 Heap Dump

獲取當(dāng)下運(yùn)行進(jìn)程的堆內(nèi)存柱狀圖

獲取內(nèi)存溢出錯(cuò)誤的堆內(nèi)存柱狀圖

監(jiān)控在等待終結(jié)的對(duì)象數(shù)量

第三方內(nèi)存調(diào)試器

調(diào)試內(nèi)存泄露問題的常用策略或步驟:

確認(rèn)征兆

啟用詳細(xì)的垃圾回收機(jī)制(verbose GC)

啟用性能分析

分析堆棧跟蹤

原文地址:https://dzone.com/articles/java-memory-architecture-model-garbage-collection

OneAPM for Java 能夠深入到所有 Java 應(yīng)用內(nèi)部完成應(yīng)用性能管理和監(jiān)控,包括代碼級(jí)別性能問題的可見性、性能瓶頸的快速識(shí)別與追溯、真實(shí)用戶體驗(yàn)監(jiān)控、服務(wù)器監(jiān)控和端到端的應(yīng)用性能管理。想閱讀更多技術(shù)文章,請?jiān)L問 OneAPM 官方博客。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/64728.html

相關(guān)文章

  • 第6章:可維護(hù)性軟件構(gòu)建方法 6.3可維護(hù)性構(gòu)建技術(shù)

    摘要:遵循特定規(guī)則,利用操作符,終止節(jié)點(diǎn)和其他非終止節(jié)點(diǎn),構(gòu)造新的字符串非終結(jié)符是表示字符串的樹的內(nèi)部節(jié)點(diǎn)。語法中的生產(chǎn)具有這種形式非終結(jié)符終結(jié),非終結(jié)符和運(yùn)算符的表達(dá)式語法的非終結(jié)點(diǎn)之一被指定為根。 大綱 基于狀態(tài)的構(gòu)建 基于自動(dòng)機(jī)的編程 設(shè)計(jì)模式:Memento提供了將對(duì)象恢復(fù)到之前狀態(tài)的功能(撤消)。 設(shè)計(jì)模式:狀態(tài)允許對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變其行為。 表驅(qū)動(dòng)結(jié)構(gòu)* 基于語法的構(gòu)...

    young.li 評(píng)論0 收藏0
  • Javag工程師成神之路(2019正式版)

    摘要:結(jié)構(gòu)型模式適配器模式橋接模式裝飾模式組合模式外觀模式享元模式代理模式。行為型模式模版方法模式命令模式迭代器模式觀察者模式中介者模式備忘錄模式解釋器模式模式狀態(tài)模式策略模式職責(zé)鏈模式責(zé)任鏈模式訪問者模式。 主要版本 更新時(shí)間 備注 v1.0 2015-08-01 首次發(fā)布 v1.1 2018-03-12 增加新技術(shù)知識(shí)、完善知識(shí)體系 v2.0 2019-02-19 結(jié)構(gòu)...

    Olivia 評(píng)論0 收藏0
  • Java學(xué)習(xí)路線總結(jié),搬磚工逆襲Java架構(gòu)師(全網(wǎng)最強(qiáng))

    摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號(hào)作者架構(gòu)師奮斗者掃描主頁左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...

    Scorpion 評(píng)論0 收藏0
  • (CZ深入淺出Java基礎(chǔ))設(shè)計(jì)模式筆記

    摘要:在設(shè)計(jì)模式中,所有的設(shè)計(jì)模式都遵循這一原則。其實(shí)就是說在應(yīng)用程序中,所有的類如果使用或依賴于其他的類,則應(yīng)該依賴這些其他類的抽象類,而不是這些其他類的具體類。使用設(shè)計(jì)模式是為了可重用代碼讓代碼更容易被他人理解保證代碼可靠性。 這是劉意老師的JAVA基礎(chǔ)教程的筆記講的賊好,附上傳送門 傳智風(fēng)清揚(yáng)-超全面的Java基礎(chǔ) 一、面向?qū)ο笏枷朐O(shè)計(jì)原則 1.單一職責(zé)原則 其實(shí)就是開發(fā)人員經(jīng)常說的高...

    李昌杰 評(píng)論0 收藏0
  • 一文理清21種設(shè)計(jì)模式:用實(shí)例分析和對(duì)比

    摘要:設(shè)計(jì)模式無論是對(duì)于最底層的的編碼實(shí)現(xiàn)還是較高層的架構(gòu)設(shè)計(jì)都有著重要的指導(dǎo)作用。所謂光說不練假把式,今天我就把項(xiàng)目中常見的應(yīng)用場景涉及到的主要設(shè)計(jì)模式及其相關(guān)設(shè)計(jì)模式總結(jié)一下,用實(shí)例分析和對(duì)比的方式在一片文章中就把最常見的種設(shè)計(jì)模式梳理清楚。 設(shè)計(jì)模式無論是對(duì)于最底層的的編碼實(shí)現(xiàn)還是較高層的架構(gòu)設(shè)計(jì)都有著重要的指導(dǎo)作用。所謂光說不練假把式,今天我就把項(xiàng)目中常見的應(yīng)用場景涉及到的主要設(shè)計(jì)模...

    PrototypeZ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<