JVM原理探究及調優方法論

1 此文目的

本文不準備從盤古開天地開始講述JVM的種種,相關的文章網上太多了,大多也無非轉來轉去,連圖都差不多。筆者只整理個提綱挈領的學習路線指南,并對自己學習過程中遇到的坑和容易混淆和忽視的地方作個總結。

2 JVM內存模型

2.1 內存模型

內存區域劃分有多個維度,相同區域在不同維度的名稱并不一樣。如下圖所示

可以看到,survivor區被劃分為了survivor0和survivor1兩個區域,但是在講MinorGC的原理時,我們又會說survvior to和survivor from兩個區域。事實上,survivor0和survivor1是物理維度的劃分,而survivor to和survivor from是邏輯維度的劃分,在MinorGC的過程中,survivor0和survivor1交替擔當to區和from區。 來仔細解釋一下MinorGC的過程: 在GC開始的時候,對象只會存在于Eden區和名為“From”的Survivor區,Survivor區“To”是空的。緊接著進行GC,Eden區中所有存活的對象都會被復制到“To”,而在“From”區中,仍存活的對象會根據他們的年齡值來決定去向。年齡達到一定值(年齡閾值,可以通過-XX:MaxTenuringThreshold來設置)的對象會被移動到年老代中,沒有達到閾值的對象會被復制到“To”區域。經過這次GC后,Eden區和From區已經被清空。這個時候,“From”和“To”會交換他們的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎樣,都會保證名為To的Survivor區域是空的。Minor GC會一直重復這樣的過程,直到“To”區被填滿,“To”區被填滿之后,會將所有對象移動到年老代中。大致如下圖所示:

2.2 方法區和永久代

這兩個概念,很多時候都被當做是同一個概念。實際上,“方法區”是java虛擬機規范中對存放類信息,字段,方法,常量,靜態變量,接口和常量池的內存區域的定義,而“永久代”則是HotSpot VM在1.8版本以前對于方法區的具體實現。由于java虛擬機規范并沒有對方法區的具體實現作限制,所以HotSpot VM和JRocket VM對于方法區的實現都是不一樣的,JRocket中就沒有永久代的概念。而在1.8及1.8以后的版本中,HotSpot VM用"元空間"--metaspace來代替永久代,實現方法區。 這個變化帶來的就是VM參數的變化,所有的PermGen都被替換成了MetaSpace。并且metaSpace不再使用堆內存,而是使用系統內存。但是該發生的OOM一樣會發生。原因也基本都是加載到內存中的 class 數量太多或者體積太大。

3.GC

3.1 GC算法

GC算法和GC收集器也是兩個維度的概念。 GC算法包括清除算法(也叫標記清除算法),復制算法,標記-整理算法。 不同垃圾收集器針對不同的內存區域,采用不同的GC算法。 具體介紹,網上相關資料很多,可以參考這篇文章:blog.csdn.net/xiaoping091…

3.2 垃圾收集器

垃圾收集器經歷了從串行收集器到并行收集器,再到并發收集器的進化過程。這三者的區別如下圖所示

串行和并行的區別比較容易理解,而CMS垃圾收集器的原理要注意的是,雖然它是并發收集器,但它的GC線程并不是完完全全地與應用的進程并發進行,它只是通過用兩次短暫停來代替并行GC的一次長暫停,以期達到減少應用線程暫停的目的,詳見CMS垃圾回收機制

不同版本默認使用的垃圾收集器以及支持開發者定制的垃圾收集器都是不一樣的 jdk1.7 默認垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代) jdk1.8 默認垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代) jdk1.9 默認垃圾收集器G1 與此同時,通過設置JVM參數也可以自己選擇垃圾收集器。如要開啟G1垃圾回收器,可以用-XX:+UseG1GC,支持G1垃圾回收器的JDK最低版本為JDK 7u4。在用戶自己選擇垃圾收集器的時候,要注意JDK版本的問題。 筆者用表格的形式列出了新生代和老年代的GC收集器的常見搭配方案:

3.3 Full GC觸發條件

頻繁FullGC導致的stop the world的現象,會大大影響系統的穩定性。盡管一代又一代的垃圾收集器的優化,使得stop the world的時間越來越短,但是在大型應用中,還是避之不及。 出發FullGC的情況有以下幾種:

  1. System.gc()方法的調用
  2. 老年代不足
  3. 方法區不足
  4. concurrent mode failure concurrent mode failure是在執行CMS GC的過程中同時有對象要放入老年代,而此時老年代空間不足造成的(有時候“空間 不足”是CMS GC時當前的浮動垃圾過多導致暫時性的空間不足觸發Full GC)。
  5. promotion failed minor gc時年輕代的存活區空間不足而晉升老年代,老年代又空間不足而觸發full gc
  6. 統計得到的Minor GC晉升到舊生代的平均大小大于老年代的剩余空間 當準備要觸發一次young GC時,如果發現統計數據說之前young GC的平均晉升大小比目前old gen剩余的空間大,則不會觸發young GC而是轉為觸發full GC(因為HotSpot VM的GC里,除了CMS的concurrent collection之外,其它能收集old gen的GC都會同時收集整個GC堆,包括young gen,所以不需要事先觸發一次單獨的young GC)。

3.3.1 OOM的類型

通常情況下,JVM的GC機制能保證應用的正常運行,導致系統頻繁FullGC的原因百分之九十都是內存溢出(OOM)。OOM分為以下幾類:

  1. Java.lang.OutOfMemeoryError:Java heap space 堆空間的內存溢出,可能的原因是某個可達性分析認為不能被回收的對象隨著時間推移變得越來越大,例如某個static類型的map對象,被不停地塞入鍵值對,也可能是大循環或者死循環不斷創建對象,而對象分配內存的速度超過了GC清理內存的速度。
  2. Java.lang.OutOfMemeoryError:GC overhead limit exceeded 這種OOM異常是Hotspot VM 1.6定義的一個策略,通過統計GC時間來預測是否要OOM了,提前拋出異常,防止OOM發生。Sun 官方對此的定義是:“并行/并發回收器在GC回收時間過長時會拋出OutOfMemroyError。過長的定義是,超過98%的時間用來做GC并且回收了不到2%的堆內存。用來避免內存過小造成應用不能正常工作。” 那么為什么會出現這種GC效率低下的現象呢?通常是因為老年代內存占有過多導致的頻繁GC,這種情況下,可以增加-verbose:gc -XX:+PrintGCDetails來分析具體原因,也可以加-XX:+HeapDumpOnOutOfMemoryError,這樣OOM時會自動做Heap Dump,第二種方法適用于所有OOM異常的排查。
  3. Java.lang.OutOfMemoryError: PermGen space(JAVA8引入了Metaspace區域)方法區內存溢出,通常是因為加載的類過多,可以先排除程序問題導致的重復類加載,或者加大方法區內存的分配
  4. Java.lang.OutOfMemoryError: unable to create new native thread 產生這種異常的原因是由于系統在不停地創建大量的線程,且不進行釋放。

4. JVM調優

4.1 調優參數

正確設置JVM參數,可以盡可能多地避免系統資源浪費,盡可能詳細地掌握系統運行情況,并且對可能出現的問題防患于未然。

Xms:堆初始空間

Xmx:堆最大空間

Xmn:年輕代大小

XX:MaxNewSize 新生代最大空間 建議設置為整個堆的1/3到1/4

XX:NewSize

XX:MaxTenuringThreshold survivor中到老年代中的年齡閾值

Xss:每個線程的棧大小

java -XX:+PrintCommandLineFlags -version 得到JDK建議的內存分配大小

tomcat設置catalina.sh:

export JAVA_OPTS="-server –Xms1024m -Xmx1024m -XX:+UseParallelOldGC -verbose:gc -Xloggc:../logs/gc.log

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps"

-XX:+PrintCommandLineFlagsjvm參數可查看默認設置收集器類型

-XX:+PrintGCDetails亦可通過打印的GC日志的新生代、老年代名稱判斷

4.2 JVM監控

  • 1.本機環境下,推薦一款idea上的插件VisualVM Launcher,實際就是聯動了JDK開發包中自帶的jvisualvm.exe監控軟件。也可以設置遠程監控。具體使用方法,可以參考這篇文章https://blog.csdn.net/wngpenghao/article/details/82884874IDEA Java性能分析插件VisualVM Launcher 配置(JAVA VisualVM 與Jconsole配置相同)

  • 2.Linux的相關命令: jstat命令可以對jvm從各維度進行統計,詳細使用參考jstat命令查看jvm的GC情況

  • 3.VM參數設置時,指定打印出gc日志 -Xloggc:../logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 詳細的參數設置以及gc日志該如何閱讀,可以參考java之GC日志該怎么看

4.3 JVM異常排查

  1. 保存dump 當使用監控軟件或者命令查看發現JVM異常時,應第一時間保存下dump現場。 命令是jmap -dump:format=b,file=文件名[pid] pid是服務進程

如果是使用jvisualvm就更方便了,直接點擊如圖所示的按鈕即可:

2. 分析dump eclipse有一款插件叫做Memory Analyzer(MAT),但是目前idea并沒有這款插件 此外,jhat是sun 1.6及以上版本中自帶的一個用于分析JVM 堆DUMP 文件的工具,基于此工具可分析JVM HEAP 中對象的內存占用情況 jhat -J-Xmx1024M [file] 執行后等待console 中輸入start HTTP server on port 7000 即可使用瀏覽器訪問 IP:7000 可以特別關心下圖標出的這個選項 這對于排查堆內存溢出非常有效

4.4 實戰例子

由于實際工作中,能接觸到JVM機會的機會并不多,所以筆者整理了一些經典實例

Metaspace溢出排查過程

分享一次 Java 內存泄漏的排查

一次生產的 JVM 優化案例

JVM成長之路,記錄一次內存溢出導致頻繁FGC的問題排查及解決

非常詳細的jvm調優實例,性能瓶頸定位

轉載于:https://juejin.im/post/5cf500c7f265da1b855c40c3

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448681.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448681.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448681.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

超方便、最簡單版本:java 郵件發送 (半分鐘寫完代碼)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. jar 和 郵箱設置 <!--郵件--><dependency><groupId>org.simplejavamail</groupId><artifactId>simpl…

OpenCL(CUDA5.0) + Visual Studio 2010 環境配置

1.安裝步驟 1&#xff09;安裝CUDA5.0本文默認的安裝目錄為&#xff1a;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA \v5.0 CUDA SDK的默認安裝目錄為&#xff1a;C:\ProgramData\NVIDIA Corporation\CUDA Samples\v5.0 其他路徑請自行修改路徑&#xff01;2&#xff…

Q-Dir

Q-dir&#xff0c;可以分界面&#xff0c;分文件夾&#xff0c;快捷選擇等優勢&#xff0c;非常好用的工具&#xff0c;可以替代微軟的File Explorer。 官網&#xff1a;https://www.softwareok.com/?seiteFreeware/Q-Dir轉載于:https://www.cnblogs.com/JTCLASSROOM/p/109719…

一行代碼 實現集合去重

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 代碼寫法&#xff1a;&#xff08;這是針對元素為基本數據類型的集合&#xff09; 針對引用類型元素去重&#xff0c;可根據元素內多…

《Mali OpenCL SDK v1.1.0》教程樣例之一“Hello World”

1、算法簡述 實現矩陣相加&#xff1a;Cn An Bn。這個例子雖然很簡單&#xff0c;但是由于矩陣元素之間相互獨立&#xff0c;每個元素可以非常容易地進行并行計算&#xff0c;可以非常理想地在OpenCL中實現。 2. C/C實現 [cpp] view plaincopyprint?/* * This confidential…

PHP商城數據庫安全事務處理方法

現在是一個電商時代&#xff0c;做電商的首先得有一個商城&#xff0c;所以商城的安全也是不容忽視的&#xff0c;一個數據安全的商城離不開數據庫的事務處理&#xff0c;商城在資金、商品、下單、結賬等重要步驟加上事務控制這是不一定不可少的&#xff0c;像市場上的一些開源…

職業規劃之ABZ,未雨綢繆35歲危機

35歲的中年人正面臨著上有老下有小&#xff0c;房貸車貸等生活壓力&#xff0c;然而在職場上又面臨被裁員或在招聘中年齡超限的尷尬局面。那么&#xff0c;我們如何應對此危機呢&#xff1f;ABZ理論為我們打開了一扇天窗。 ABZ理論由著名的創業者投資人&#xff0c;LinkedIn和P…

集合去重 (集合元素為引用類型)--- java 8 新特性 --- 根據元素單屬性、多屬性實現去重

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 代碼寫法&#xff1a; &#xff08;要求 JDK 1.8 或 1.8 以上&#xff09; package gentle.entity;import lombok.Data; /**** auth…

Django--Forms組件使用

Forms組件的使用 在html表單驗證中&#xff0c;需要通過各種信息的驗證&#xff0c;比如注冊界面的姓名、密碼、郵箱、電話等的驗證&#xff0c;是否符合定義好的規則&#xff0c;不可能每次都要取出對應的字段一一判斷&#xff0c;django內置了Forms組件&#xff0c;可以方便的…

yii2關聯表

asArray()這個方法很好用&#xff0c;返回數組是1版本想要的形式&#xff0c;這種方式有種tp框架的感覺轉載于:https://www.cnblogs.com/peipeiyu/p/10974487.html

詳細程序注解學OpenCL一 環境配置和入門程序

本專欄是通過注解程序的方法學習OpenCL&#xff0c;我覺得一個一個地去摳原理也不是辦法&#xff0c;干脆直接學習程序&#xff0c;然后把相關原理都直接注解到程序語句當中。 原創地址&#xff1a;http://blog.csdn.net/kenden23/article/details/14101657 一開始要配置好環境…

解決 IDEA 在 commit 代碼時 git 日志亂碼 (提交時填寫的中文說明亂碼)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.問題描述&#xff1a; idea 開發代碼中的 中文正常&#xff0c;但提交到碼云時填寫的提交日志是亂碼。 提交到碼云后是這樣的&#…

Box 類

public class Box extends JComponent implements Accessible使用 BoxLayout 對象作為其布局管理器的一個輕量級容器。Box 提供幾個對使用 BoxLayout 的容器&#xff08;甚至非 Box 容器&#xff09;有用的類方法。 Box 類可以創建幾種影響布局的不可見組件&#xff1a;glue、s…

神奇的pdfkit工具——將字符串保存為pdf文件

神奇的pdfkit工具——將字符串保存為pdf文件 1、安裝工具包 pip install pdfkit 2、上干貨 import pdfkitdef create_pdf(str_data, to_file):將字符串生成pdf文件 # &#xff08;需下載wkhtmltox&#xff09;將程序路徑傳入config對象config pdfkit.configuration(wkhtmltopd…

OpenCL結構

原標題&#xff1a;從零開始學習OpenCL開發&#xff08;一&#xff09;架構 1 異構計算、GPGPU與OpenCL OpenCL是當前一個通用的由很多公司和組織共同發起的多CPU\GPU\其他芯片 異構計算&#xff08;heterogeneous&#xff09;的標準&#xff0c;它是跨平臺的。旨在充分利用GP…

docker-compose 使用小例

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 只是一個很簡單的小例。 1. 原本有的容器 2. docker-compose.yml 寫法&#xff1a; gentle 處可以任意寫&#xff0c;gentle 是我的項…

2019.6.20

今日內容 MongoDB可視化工具 一、Scrapy爬蟲框架 二、微信機器人 轉載于:https://www.cnblogs.com/jrc123/p/11062606.html

PCL點云 Lebel:Research

https://blog.csdn.net/wokaowokaowokao12345/article/details/73741957 https://blog.csdn.net/u010696366/article/category/3108337轉載于:https://www.cnblogs.com/radiumlrb/p/10986918.html

AMD GPU+VS2010的OpenCL配置

安裝開發環境可以參照DE4-530的OpenCL開發環境搭建&#xff08;最終版&#xff09;&#xff0c;這篇文章的大部分內容轉載自&#xff1a;http://www.verydemo.com/demo_c92_i226325.html AMD的Heterogeneous Computing有很多AMD的OpenCL資料&#xff0c;包括各種分析工具&#…

ABP開發框架前后端開發系列---(9)ABP框架的權限控制管理

在前面兩篇隨筆《ABP開發框架前后端開發系列---&#xff08;7&#xff09;系統審計日志和登錄日志的管理》和《ABP開發框架前后端開發系列---&#xff08;8&#xff09;ABP框架之Winform界面的開發過程》開始介紹了權限管理的內容&#xff0c;其中只是列出了內部的權限系統的審…