實戰Java虛擬機-實戰篇

一、內存調優

1.內存溢出和內存泄漏

  • 內存泄漏(memory leak):在Java中如果不再使用一個對象,但是該對象依然在GC ROOT的引用鏈上,這個對象就不會被垃圾回收器回收,這種情況就稱之為內存泄漏。
  • 內存泄漏絕大多數情況都是由堆內存泄漏引起的,所以后續沒有特別說明則討論的都是堆內存泄漏。

2.內存泄漏的常見場景?

  • 內存泄漏導致溢出的常見場景是大型的Java后端應用中,在處理用戶的請求之后,沒有及時將用戶的數據刪除。隨著用戶請求數量越來越多,內存泄漏的對象占滿了堆內存最終導致內存溢出。
  • 這種產生的內存溢出會直接導致用戶請求無法處理,影響用戶的正常使用。重啟可以恢復應用使用,但是在運行一段時間之后依然會出現內存溢出。
  • 第二種常見場景是分布式任務調度系統如Elastic-job、Quartz等進行任務調度時,被調度的Java應用在調度任務結束中出現了內存泄漏,最終導致多次調度之后內存溢出。
  • 這種產生的內存溢出會導致應用執行下次的調度任務執行。同樣重啟可以恢復應用使用,但是在調度執行一段時間之后依然會出現內存溢出。

3.解決內存溢出的思路

檢測問題工具

Top命令
  • top命令是linux下用來查看系統信息的一個命令,它提供給我們去實時地去查看系統的資源,比如執行時的進程、線程和系統參數等信息。
  • 進程使用的內存為RES(常駐內存)- SHR(共享內存)

VisualVM
  • VisualVM是多功能合一的Java故障排除工具并且他是一款可視化工具,整合了命令行 JDK 工具和輕量級分析功能,功能非常強大。
  • 這款軟件在Oracle JDK 6~8 中發布,但是在 Oracle JDK 9 之后不在JDK安裝目錄下需要單獨下載。下載地址:https://visualvm.github.io/

Arthas

Arthas 是一款線上監控診斷產品,通過全局視角實時查看應用 load、內存、gc、線程的狀態信息,并能在不修改應用代碼的情況下,對業務問題進行診斷,包括查看方法調用的出入參、異常,監測方法執行耗時,類加載信息等,大大提升線上問題排查效率。

Prometheus + Grafana

Prometheus+Grafana是企業中運維常用的監控方案,其中Prometheus用來采集系統或者應用的相關數據,同時具備告警功能。Grafana可以將Prometheus采集到的數據以可視化的方式進行展示。

堆內存狀況的對比

產生內存溢出原因一 :代碼中的內存泄漏

1、equals()和hashCode()導致的內存泄漏

2、非靜態的內部類和匿名內部類的錯誤使用導致內存泄漏

3、由于線程池中的線程不被回收導致的ThreadLocal內存泄漏

4、由于JDK6中的字符串常量池位于永久代,intern被大量調用并保存產生的內存泄漏

5、大量的數據在靜態變量中被引用,但是不再使用,成為了內存泄漏

產生內存溢出原因二 : 并發請求問題

  • 并發請求問題指的是用戶通過發送請求向Java應用獲取數據,正常情況下Java應用將數據返回之后,這部分數據就可以在內存中被釋放掉。
  • 并發請求問題指的是用戶通過發送請求向Java應用獲取數據,正常情況下Java應用將數據返回之后,這部分數據就可以在內存中被釋放掉。但是由于用戶的并發請求量有可能很大,同時處理數據的時間很長,導致大量的數據存在于內存中,最終超過了內存的上限,導致內存溢出。這類問題的處理思路和內存泄漏類似,首先要定位到對象產生的根源。

診斷 – 內存快照

  • 當堆內存溢出時,需要在堆內存溢出時將整個堆內存保存下來,生成內存快照(Heap Profile )文件。
    • 生成內存快照的Java虛擬機參數:
      • ??? -XX:+HeapDumpOnOutOfMemoryError:發生OutOfMemoryError錯誤時,自動生成hprof內存快照文件。
      • -XX:HeapDumpPath=<path>:指定hprof文件的輸出路徑。
  • 使用MAT打開hprof文件,并選擇內存泄漏檢測功能,MAT會自行根據內存快照中保存的數據分析內存泄漏的根源。

MAT內存泄漏檢測的原理 – 支配樹

MAT提供了稱為支配樹(Dominator Tree)的對象圖。支配樹展示的是對象實例間的支配關系。在對象引用圖中,所有指向對象B的路徑都經過對象A,則認為對象A支配對象B。

MAT內存泄漏檢測的原理 – 深堆和淺堆

支配樹中對象本身占用的空間稱之為淺堆(Shallow Heap)。

支配樹中對象的子樹就是所有被該對象支配的內容,這些內容組成了對象的深堆(Retained Heap),也稱之為保留集( Retained Set )?。深堆的大小表示該對象如果可以被回收,能釋放多大的內存空間。

解決內存溢出的思路

修復問題

并發引起內存溢出 – 設計不當
  • 系統的方案設計不當,比如:
  • 從數據庫獲取超大數據量的數據
  • 線程池設計不當,生產者-消費者模型,消費者消費性能問題

解決方案:優化設計方案

并發引起內存溢出 - 參數不當
  • 由于參數設置不當,比如堆內存設置過小,導致并發量增加之后超過堆內存的上限。

解決方案:調整參數,

二、GC調優

GC調優

  • GC調優指的是對垃圾回收(Garbage Collection)進行調優。GC調優的主要目標是避免由垃圾回收引起程序性能下降。

GC調優的核心分成三部分:

1、通用Jvm參數的設置。

2、特定垃圾回收器的Jvm參數的設置。

3、解決由頻繁的FULLGC引起的程序性能問題。

GC調優沒有沒有唯一的標準答案,如何調優與硬件、程序本身、使用情況均有關系,重點學習調優的工具和方法。

GC調優的核心指標

所以判斷GC是否需要調優,需要從三方面來考慮,與GC算法的評判標準類似:

1.吞吐量(Throughput) 吞吐量分為業務吞吐量和垃圾回收吞吐量

業務吞吐量指的在一段時間內,程序需要完成的業務數量。比如企業中對于吞吐量的要求可能會是這樣的:

  • 支持用戶每天生成10000筆訂單
  • 在晚上8點到10點,支持用戶查詢50000條商品信息

保證高吞吐量的常規手段有兩條:

1、優化業務執行性能,減少單次業務的執行時間

2、優化垃圾回收吞吐量

垃圾回收吞吐量

垃圾回收吞吐量指的是 CPU 用于執行用戶代碼的時間與 CPU 總執行時間的比值,即吞吐量 = 執行用戶代碼時間 /(執行用戶代碼時間 + GC時間)。吞吐量數值越高,垃圾回收的效率就越高,允許更多的CPU時間去處理用戶的業務,相應的業務吞吐量也就越高。

2. 延遲(Latency)

延遲指的是從用戶發起一個請求到收到響應這其中經歷的時間。比如企業中對于延遲的要求可能會是這樣的:

所有的請求必須在5秒內返回給用戶結果

延遲 = GC延遲 + 業務執行時間,所以如果GC時間過長,會影響到用戶的使用。

3. 內存使用量

內存使用量指的是Java應用占用系統內存的最大值,一般通過Jvm參數調整,在滿足上述兩個指標的前提下,這個值越小越好。

發現問題工具

jstat工具

  • Jstat工具是JDK自帶的一款監控工具,可以提供各種垃圾回收、類加載、編譯信息等不同的數據。
  • 使用方法為:jstat -gc 進程ID 每次統計的間隔(毫秒) 統計次數

visualvm插件

VisualVm中提供了一款Visual Tool插件,實時監控Java進程的堆內存結構、堆內存變化趨勢以及垃圾回收時間的變化趨勢。同時還可以監控對象晉升的直方圖。

Prometheus + Grafana

Prometheus+Grafana是企業中運維常用的監控方案,其中Prometheus用來采集系統或者應用的相關數據,同時具備告警功能。Grafana可以將Prometheus采集到的數據以可視化的方式進行展示。

GC日志

  • 通過GC日志,可以更好的看到垃圾回收細節上的數據,同時也可以根據每款垃圾回收器的不同特點更好地發現存在的問題。
  • 使用方法(JDK 8及以下):-XX:+PrintGCDetails -Xloggc:文件名
  • 使用方法(JDK 9+):-Xlog:gc*:file=文件名

GC Viewer

GCViewer是一個將GC日志轉換成可視化圖表的小工具,github地址:

https://github.com/chewiebug/GCViewer

使用方法:java -jar gcviewer_1.3.4.jar 日志文件.log

GCeasy

GCeasy是業界首款使用AI機器學習技術在線進行GC分析和診斷的工具。定位內存泄漏、GC延遲高的問題,提供JVM參數優化建議,支持在線的可視化工具圖表展示。

官方網站:https://gceasy.io/

常見的GC模式

特點:呈現鋸齒狀,對象創建之后內存上升,一旦發生垃圾回收之后下降到底部,并且每次下降之后的內存大小接近,存留的對象較少。

一、正常情況

特點:呈現鋸齒狀,對象創建之后內存上升,一旦發生垃圾回收之后下降到底部,并且每次下降之后的內存大小接近,存留的對象較少。

二、緩存對象過多

特點:呈現鋸齒狀,對象創建之后內存上升,一旦發生垃圾回收之后下降到底部,并且每次下降之后的內存大小接近,處于比較高的位置。

問題產生原因: 程序中保存了大量的緩存對象,導致GC之后無法釋放,可以使用MAT或者HeapHero等工具進行分析內存占用的原因。

三、內存泄漏

特點:呈現鋸齒狀,每次垃圾回收之后下降到的內存位置越來越高,最后由于垃圾回收無法釋放空間導致對象無法分配產生OutOfMemory的錯誤。

問題產生原因: 程序中保存了大量的內存泄漏對象,導致GC之后無法釋放,可以使用MAT或者HeapHero等工具進行分析是哪些對象產生了內存泄漏。

四、持續的FullGC

特點:在某個時間點產生多次Full GC,CPU使用率同時飆高,用戶請求基本無法處理。一段時間之后恢復正常。
問題產生原因: 在該時間范圍請求量激增,程序開始生成更多對象,同時垃圾收集無法跟上對象創建速率,導致·持續地在進行FULL GC。GC分析報告

五、元空間不足導致的FULLGC

特點:堆內存的大小并不是特別大,但是持續發生FULLGC。

問題產生原因: 元空間大小不足,導致持續FULLGC回收元空間的數據。GC分析報告

解決GC問題的手段

優化基礎JVM參數

參數1 : -Xmx 和 –Xms

-Xmx參數設置的是最大堆內存,但是由于程序是運行在服務器或者容器上,計算可用內存時,要將元空間、操作系統、其它軟件占用的內存排除掉。

優化基礎JVM參數
參數1 : -Xmx 和 –Xms

-Xms用來設置初始堆大小,建議將-Xms設置的和-Xmx一樣大,有以下幾點好處:

  • 運行時性能更好,堆的擴容是需要向操作系統申請內存的,這樣會導致程序性能短期下降。
  • 可用性問題,如果在擴容時其他程序正在使用大量內存,很容易因為操作系統內存不足分配失敗。
  • 啟動速度更快,Oracle官方文檔的原話:如果初始堆太小,Java 應用程序啟動會變得很慢,因為 JVM 被迫頻繁執行垃圾收集,直到堆增長到更合理的大小。為了獲得最佳啟動性能,請將初始堆大小設置為與最大堆大小相同。
參數2 : -XX:MaxMetaspaceSize 和 –XX:MetaspaceSize

-XX:MaxMetaspaceSize=值 參數指的是最大元空間大小,默認值比較大,如果出現元空間內存泄漏會讓操作系統可用內存不可控,建議根據測試情況設置最大值,一般設置為256m。

-XX:MetaspaceSize=值 參數指的是到達這個值之后會觸發FULLGC(網上很多文章的初始元空間大小是錯誤的),后續什么時候再觸發JVM會自行計算。如果設置為和MaxMetaspaceSize一樣大,就不會FULLGC,但是對象也無法回收。

參數3 : -Xss虛擬機棧大小

如果我們不指定棧的大小,JVM 將創建一個具有默認大小的棧。大小取決于操作系統和計算機的體系結構。
比如Linux x86 64位 : 1MB,如果不需要用到這么大的棧內存,完全可以將此值調小節省內存空間,合理值為256k – 1m之間。

使用:-Xss256k

參數4 : 不建議手動設置的參數

由于JVM底層設計極為復雜,一個參數的調整也許讓某個接口得益,但同樣有可能影響其他更多接口。

‐XX:SurvivorRatio 伊甸園區和幸存者區的大小比例,默認值為8。

‐XX:MaxTenuringThreshold 最大晉升閾值,年齡大于此值之后,會進入老年代。另外JVM有動態年齡判斷機制:將年齡從小到大的對象占據的空間加起來,如果大于survivor區域的50%,然后把等于或大于該年齡的對象,放入到老年代。

其他參數 :
  • -XX:+DisableExplicitGC

禁止在代碼中使用System.gc(), System.gc()可能會引起FULLGC,在代碼中盡量不要使用。使用
DisableExplicitGC參數可以禁止使用System.gc()方法調用。

  • -XX:+HeapDumpOnOutOfMemoryError:發生OutOfMemoryError錯誤時,自動生成hprof內存快照文件。

-XX:HeapDumpPath=<path>:指定hprof文件的輸出路徑。

  • 打印GC日志

JDK8及之前 : -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:文件路徑

JDK9及之后 : -Xlog:gc*:file=文件路徑

JVM參數模板:

-Xms1g
-Xmx1g
-Xss256k
-XX:MaxMetaspaceSize=512m
-XX:+DisableExplicitGC
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/logs/my-service.hprof
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:文件路徑

注意:

JDK9及之后gc日志輸出修改為 -Xlog:gc*:file=文件名

堆內存大小和棧內存大小根據實際情況靈活調整。

垃圾回收器的選擇

垃圾回收器的組合關系

垃圾回收器是垃圾回收算法的具體實現。

性能調優

應用程序在運行過程中經常會出現性能問題,比較常見的性能問題現象是:

1、通過top命令查看CPU占用率高,接近100甚至多核CPU下超過100都是有可能的。

2、請求單個服務處理時間特別長,多服務使用skywalking等監控系統來判斷是哪一個環節性能低下。

3、程序啟動之后運行正常,但是在運行一段時間之后無法處理任何的請求(內存和GC正常)。

線程轉儲的查看方式

線程轉儲(Thread Dump)提供了對所有運行中的線程當前狀態的快照。線程轉儲可以通過jstack、visualvm等工具獲取。其中包含了線程名、優先級、線程ID、線程狀態、線程棧信息等等內容,可以用來解決CPU占用率高、死鎖等問題。

線程轉儲(Thread Dump)中的幾個核心內容:

  • 名稱: 線程名稱,通過給線程設置合適的名稱更容易“見名知意”
  • 優先級(prio):線程的優先級
  • Java ID(tid):JVM中線程的唯一ID
  • 本地 ID (nid):操作系統分配給線程的唯一ID
  • 狀態:線程的狀態,分為:
    • NEW – 新創建的線程,尚未開始執行
    • RUNNABLE –正在運行或準備執行
    • BLOCKED – 等待獲取監視器鎖以進入或重新進入同步塊/方法
    • WAITING – 等待其他線程執行特定操作,沒有時間限制
    • TIMED_WAITING – 等待其他線程在指定時間內執行特定操作
    • TERMINATED – 已完成執行
  • TERMINATED – 已完成執行

更精細化的性能測試

JIT對程序性能的影響

Java程序在運行過程中,JIT即時編譯器會實時對代碼進行性能優化,所以僅憑少量的測試是無法真實反應運行系統最終給用戶提供的性能。如下圖,隨著執行次數的增加,程序性能會逐漸優化。

正確地測試代碼性能

OpenJDK中提供了一款叫JMH(Java Microbenchmark Harness)的工具,可以準確地對Java代碼進行基準測試,量化方法的執行性能。

官網地址:https://github.com/openjdk/jmh

JMH會首先執行預熱過程,確保JIT對代碼進行優化之后再進行真正的迭代測試,最后輸出測試的結果。

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

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

相關文章

一番賞小程序開發,為玩家帶來線上抽賞魅力

隨著人們對娛樂消費的增加&#xff0c;以及二次元文化的快速發展&#xff0c;以動漫IP為主的一番賞受到了越來越多的年輕人關注&#xff0c;一番賞市場迎來了黃金發展期&#xff01; 一番賞的運營模式是以“限量”為主&#xff0c;不管什么商品數量都是有限的&#xff0c;因此…

微軟剛發布的Copilot+PC為什么讓Intel和AMD尷尬?2024 AI PC元年——產業布局及前景展望

美國東部時間5月20日在微軟位于華盛頓的新園區舉行的發布會上&#xff0c;宣布將旗下AI助手Copilot全面融入Windows系統&#xff0c;能夠在不調用云數據中心的情況下處理更多人工智能任務。 “將世界作為一個提示詞就從Windows系統開始”。微軟的新PC將是“CopilotPC”&#xf…

[Algorithm][回溯][記憶化搜索][最長遞增子序列][猜數字大小Ⅱ][矩陣中的最長遞增路徑]詳細講解

目錄 1.最長遞增子序列1.題目鏈接2.算法原理詳解3.代碼實現 2.猜數字大小 II1.題目鏈接2.算法原理詳解3.代碼實現 3.矩陣中的最長遞增路徑1.題目鏈接2.算法原理詳解3.代碼實現 1.最長遞增子序列 1.題目鏈接 最長遞增子序列 2.算法原理詳解 題目解析&#xff1a;從每個位置&am…

內部類知識點

什么是內部類&#xff1f; 內部類何時出現&#xff1f;B類是A類的一部分&#xff0c;且B單獨存在無意義 內部類分類 成員內部類&#xff1a; 當內部類被private修飾后&#xff0c;不能用方法2 調用外部類成員變量 內部類里面有隱藏的outer this來記錄 靜態內部類 創建對象&…

警惕Mallox勒索病毒的最新變種hmallox,您需要知道的預防和恢復方法。

引言 &#xff1a; 在數字化時代&#xff0c;數據已成為企業和個人最寶貴的資產之一。然而&#xff0c;隨著技術的不斷發展&#xff0c;網絡威脅也日益猖獗&#xff0c;其中.hmallox勒索病毒以其獨特的加密手段和狡猾的傳播方式&#xff0c;成為了網絡安全領域的一顆“隱形炸彈…

水電集中抄表是什么?

1.定義分析&#xff1a;水電集中抄表 水電集中抄表是一種現代化能源管理體系方法&#xff0c;它利用先進的信息科技&#xff0c;如物聯網技術、云計算等&#xff0c;完成對水電表數據的遠程智能采集與處理。這種方法改變了傳統的人工上門服務抄表方式&#xff0c;提高了效率&a…

Biome-BGC生態系統模型與Python融合技術實踐應用

Biome-BGC是利用站點描述數據、氣象數據和植被生理生態參數&#xff0c;模擬日尺度碳、水和氮通量的有效模型&#xff0c;其研究的空間尺度可以從點尺度擴展到陸地生態系統。 在Biome-BGC模型中&#xff0c;對于碳的生物量積累&#xff0c;采用光合酶促反應機理模型計算出每天…

ECharts實現地圖飛線

echarts版本&#xff1a;https://echarts.apache.org/zh/changelog.html v5.x.x版本&#xff1a;不提供china.js和china.json文件 v4.x.x版本&#xff1a;使用npm安裝echarts&#xff0c;默認包含china.js和china.json文件 目錄 一、Html工程 二、vue工程 三、vue工程 四、矢…

c/c++ 編譯過程

C的編譯過程通常可以分為四個階段&#xff1a;預處理、編譯、匯編和鏈接。下面是這四個階段的詳細說明&#xff1a; 預處理&#xff08;Preprocessing&#xff09;&#xff1a;在這個階段&#xff0c;預處理器&#xff08;cpp&#xff09;會處理源代碼文件中的預處理指令&#…

【科普知識】伺服電機中的內置制動器

在工業自動化和機器人技術快速發展的今天&#xff0c;伺服電機作為核心驅動元件&#xff0c;其性能與功能直接影響整個系統的運行效率與穩定性。 近年來&#xff0c;一體化伺服電機技術不斷融合創新&#xff0c;并逐步加入了許多新的硬件和軟件的功能&#xff0c;為工業自動化領…

【施磊】C++語言基礎提高:深入學習C++語言先要練好的內功

課程總目錄 文章目錄 一、進程的虛擬地址空間內存劃分和布局二、函數的調用堆棧詳細過程三、程序編譯鏈接原理1. 編譯過程2. 鏈接過程 一、進程的虛擬地址空間內存劃分和布局 任何的編程語言 → \to → 產生兩種東西&#xff1a;指令和數據 編譯鏈接完成之后會產生一個可執行…

python畢設項目選題匯總(全)

各位計算機方面的畢業生們&#xff0c;是不是在頭疼畢業論文寫什么呢&#xff0c;我這給大家提供點思路&#xff1a; 網站系統類 《基于python的招聘數據爬蟲設計與實現》 《基于python和Flask的圖書管理系統》 《基于照片分享的旅游景點推薦系統》 《基于djangoxadmin的學生信…

LeetCode hot100-47-N

105. 從前序與中序遍歷序列構造二叉樹給定兩個整數數組 preorder 和 inorder &#xff0c;其中 preorder 是二叉樹的先序遍歷&#xff0c; inorder 是同一棵樹的中序遍歷&#xff0c;請構造二叉樹并返回其根節點。這題放選擇題里還能選出來&#xff0c;前序中序一起確定了一顆什…

Linux備份服務及rsync企業備份架構(應用場景)

備份服務概述 備份服務:需要使用到腳本,打包備份,定時任務. 備份服務:rsyncd服務,不同主機之間數據傳輸. 特點&#xff1a; rsync是個服務也是命令使用方便&#xff0c;具有多種模式傳輸數據的時候是增量傳輸 增量與全量&#xff1a; 全量 &#xff1a;無論多少數據全部推…

貪心算法:合并區間

參考資料&#xff1a;代碼隨想錄 題目鏈接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 做過用最少數量的箭引爆氣球和無重疊區間這兩道題目后&#xff0c;題意和題解都不難理解。唯一的一點兒難點是對于api的運用。 class Solution {public int[][] merge(int[][…

設備管理全解析:從選購到報廢的全方位指南

在現代企業快速發展、智能化運營過程中&#xff0c;企業設備管理是保障生產連續性和效率的核心環節&#xff0c;其重要性不言而喻。然而&#xff0c;許多企業在設備管理內容流程方面仍然使用傳統管理辦法&#xff0c;這不僅影響了生產效率&#xff0c;也增加了不必要的成本。那…

vuejs路由和組件系統

前端路由原理 createRouter * hash* window.addEventListener(hashChange)* 兩種實現路由切換的模式&#xff1a;UI組件&#xff08;router-link&#xff0c;router-view&#xff09;&#xff0c;Api&#xff08;push()方法&#xff09; * history * HTML5新增的API &#xff0…

每日一題(1)

在看一本08年出版的書的時候&#xff0c;看到了這樣一個問題&#xff0c;感覺答案很奇怪&#xff1a; public class demo_p22 {public static void main(String args[]){int sCook1,sFish2;//各技能標記character ch1new character();if(ch1.haveSkill(sCook))System.out.print…

仙樂健康科技股份有限公司「E立方仿生增效技術平臺」推出新品啦

在這個看臉的顏值經濟時代,很多女性將肌膚保養作為人生的“必修課”,從各種網上攻略到高端護膚品,再到美容院的專業護理,可以說是應有盡有。最近,仙樂健康科技股份有限公司「E立方仿生增效技術平臺」推出的新品——PQQ鹽膠原小分子肽樺樹汁飲品,就受到了頗多追求健康美人士的關…