1. 程式人生 > >JVM 中你不得不知的一些引數

JVM 中你不得不知的一些引數

有的同學雖然寫了一段時間 Java 了,但是對於 JVM 卻不太關注。有的同學說,引數都是團隊規定好的,部署的時候也不用我動手,關注它有什麼用,而且,JVM 這東西,聽上去就感覺很神祕很高深的樣子,還是算了吧。

沒錯,部署的時候可能用不到你親自動手,但是出現問題了怎麼辦,難道不用你解決問題嗎,如果對 JVM 瞭解不夠的話,有些問題可能排查起來就很費力,或者根本無法解決。

本篇以 JDK Hotspot 8 為背景,介紹一下 JVM 的常用引數。建議你在做一些小專案、小 demo 的時候,也把這些引數加上,加深印象。以我的經驗來看,有些知識你剛開始接觸的時候會感覺很難理解,但是沒關係,萬事開頭難嘛,知識點都是需要消化時間的。第一天不理解,甚至過了一個月也不理解,但是總有那麼一刻,你會突然有種茅塞頓開的感覺,感覺一下子通了。最後心裡面感謝自己在多少多少天以前能夠開始學習並堅持學習這些知識點。

只介紹一些常用引數,除了這些常用引數外,Hotspot 還提供了很多其他的引數,每一個都值得考究。

在使用這些引數之前,你需要對 Java 記憶體模型有一定的瞭解,可以讀一下 這篇文章 瞭解一下記憶體模型。

還是要把記憶體模型圖放在這裡,方便理解。

堆引數:

-Xms: 堆的初始值,例如 -Xmx2048,初始堆大小為 2G

-Xmx: 堆的最大值,例如 -Xmx2048M,允許最大堆記憶體 2G

-Xmn: 新生代大小

-XX:SurvivorRatio:Eden 區所佔比例,預設是 8,也就是 80%,例如 -XX:SurvivorRatio=8

最好將 -Xms 和 -Xmx 的值設定成一樣的值,這樣做是為了防止隨著堆空間使用量增加,會動態的調整堆空間大小,有一定的效能損耗,不如開始就設定成相同的值,來規避效能損失。

棧引數

-Xss:棧空間大小,棧是執行緒獨佔的,所以是一個執行緒使用棧空間的大小,例如 -Xss256K,如果不設定此引數,預設值是 1M,一般來講設定成 256K 就足夠了。

Metaspace 引數

-XX:MetaspaceSize:Metaspace 空間初始大小,如果不設定的話,預設是20.79M,這個初始大小是觸發首次 Metaspace Full GC 的閾值,例如 -XX:MetaspaceSize=256M

-XX:MaxMetaspaceSize:Metaspace 最大值,預設不限制大小,但是線上環境建議設定,例如

-XX:MaxMetaspaceSize=256M

-XX:MinMetaspaceFreeRatio:最小空閒比,當 Metaspace 發生 GC 後,會計算 Metaspace 的空閒比,如果空閒比(空閒空間/當前 Metaspace 大小)小於此值,就會觸發 Metaspace 擴容。預設值是 40 ,也就是 40%,例如 -XX:MinMetaspaceFreeRatio=40

-XX:MaxMetaspaceFreeRatio:最大空閒比,當 Metaspace 發生 GC 後,會計算 Metaspace 的空閒比,如果空閒比(空閒空間/當前 Metaspace 大小)大於此值,就會觸發 Metaspace 釋放空間。預設值是 70 ,也就是 70%,例如 -XX:MaxMetaspaceFreeRatio=70

建議將 MetaspaceSize 和 MaxMetaspaceSize 設定為同樣大小,避免頻繁擴容。

GC 日誌

簡單日誌

-verbose:gc 或者 -XX:+PrintGC

日誌格式:

[GC (Allocation Failure)  7892K->5646K(19456K), 0.0060442 secs]
[GC (Allocation Failure) , 0.0066315 secs]
[Full GC (Allocation Failure)  19302K->13646K(19456K), 0.0032698 secs]

詳細日誌

#列印詳細日誌
-XX:+PrintGCDetails
#列印 GC 的時間點
-XX:+PrintGCDateStamps

日誌格式:

2019-11-13T14:06:46.099-0800: [GC (Allocation Failure) 2019-11-13T14:06:46.099-0800: [DefNew (promotion failed) : 9180K->9157K(9216K), 0.0084297 secs]2019-11-13T14:06:46.107-0800: [Tenured: 10145K->10145K(10240K), 0.0035768 secs] 13802K->13646K(19456K), [Metaspace: 3895K->3895K(1056768K)], 0.0120887 secs] [Times: user=0.00 sys=0.00, real=0.02 secs] 
2019-11-13T14:06:47.243-0800: [Full GC (Allocation Failure) 2019-11-13T14:06:47.244-0800: [Tenured: 10145K->10145K(10240K), 0.0042686 secs] 19304K->19146K(19456K), [Metaspace: 3895K->3895K(1056768K)], 0.0043232 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

以下幾個 GC 日誌相關的引數列印的內容比較多,生產環境可選擇性開啟,大多數時候不需要開啟。

GC 前後的堆資訊

-XX:+PrintHeapAtGC

{Heap before GC invocations=0 (full 0):
 def new generation   total 9216K, used 7892K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  eden space 8192K,  96% used [0x00000007bec00000, 0x00000007bf3b5200, 
  xxx....
  class space    used 445K, capacity 462K, committed 512K, reserved 1048576K
Heap after GC invocations=1 (full 0):
 def new generation   total 9216K, used 1023K [0x00000007bec00000,
 xxx...
 Metaspace       used 3892K, capacity 4646K, committed 4864K, reserved 1056768K
  class space    used 445K, capacity 462K, committed 512K, reserved 1048576K
}

GC 導致的 Stop the world 時間

-XX:+PrintGCApplicationStoppedTime

Total time for which application threads were stopped: 0.0070384 seconds, Stopping threads took: 0.0000200 seconds

載入類資訊

-verbose:class

[Loaded java.net.URLClassLoader$3$1 from /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/rt.jar]

GC 前後的類載入情況

-XX:+PrintClassHistogramBeforeFullGC
-XX:+PrintClassHistogramAfterFullGC
 num     #instances         #bytes  class name
----------------------------------------------
   1:           140       19016264  [B
   2:          2853         226256  [C
   3:           138         169072  [I
   4:           761          86240  java.lang.Class
   5:          2850          68400  java.lang.String
   6:           660          41024  [Ljava.lang.Object;

日誌輸出到檔案

以上引數配置好之後,預設會輸出到控制檯或者服務指定的統一日誌的位置。但是這裡還會有服務的一般性資訊日誌、錯誤日誌等,都混在一起的話會比較亂,所以,一般都會把 jvm 日誌單獨存放。

#GC 活動日誌,根據配置的引數輸出內容
-Xloggc:/Users/fengzheng/jvmlog/gc.log

#致命錯誤日誌,只有在 jvm 發生崩潰的時候會輸出
-XX:ErrorFile=/Users/fengzheng/jvmlog/hs_err_pid%p.log

堆溢位現場保留

有些錯誤雖然不會導致 jvm 崩潰,但是對於服務而言也是非常嚴重的,比如stackOverflow、OutOfMemoryError,發生錯誤後,留存現場資訊對分析錯誤原因是至關重要的。jvm 提供了保留堆溢位現場的方法,對於 JDK 8 而言,可能是 heap 溢位,也可能是 Metasapce 溢位。

-XX:HeapDumpPath=/Users/fengzheng/jvmlog
-XX:+HeapDumpOnOutOfMemoryError

最後出現異常後,儲存的檔案格式為 java_pidxxx.hprof,pid 後面是發生溢位的程序 id,之後可以用 VisualVM、JProfiler 等工具開啟分析。

設定垃圾回收器型別

隨著 JDK 版本的升級,可使用的垃圾收集器型別也越來越多了。JDK 8 可使用的垃圾收集器有 7 種,當然有點只適用於年輕代,有點只使用於老年代,JDK 8 中最新的垃圾收集器是 G1,可以用於年輕代和老年代。到了 JDK 11,還出了 ZGC。

下圖是 JDK 8 中可使用的垃圾收集器以及它們配合使用的關係。

Serial、ParNew、Parallel Scavenge 只適用於年輕代,CMS、Serial Old、Parallel Old 只適用於老年代,而 G1 通用於年輕代和老年代。連線表示它們之間可配合使用的關係,其中 CMS 和 Serial Old 連線的意思是說 Serial Old 會作為 CMS 的後預案,當 CMS 發生 Concurrent Mode Failure 時啟用。

在 JDK 8 中,如果不指定垃圾收集器,預設使用引數 -XX:+UseParallelGC,新生代使用 Parallel Scavenge,老年代使用 Serial Old。

-XX:+UseSerialGC:使用 Serial + Serial Old ,運行於 client 模式下的預設設定

-XX:+UseConcMarkSweepGC:使用 ParNew+CMS+Serial Old,CMS 垃圾收集器

-XX:+UseParallelGC:Parallel Scavenge + Serial Old,JDK 8 server 模式下的預設設定

-XX:+UseParallelOldGC:Parallel Scavenge + Parallel Old

-XX:+UseG1GC:使用 G1 垃圾收集器

開啟遠端 JMX 監控

除了日誌外,當我們需要實時檢視 JVM 執行情況的時候怎麼辦,當然可以到 JVM 所在伺服器用 jstack、jmap、jinfo 等工具進行檢視,但是又不夠直觀,這時候就需要開啟 JMX 遠端功能,使用 jConsole、VisualVM 等工具進行監控。或者自己開發監控平臺,比如我之前就做了一個 web 版的簡易 VisualVm。無意中就做了個 web 版 JVM 監控端

開啟引數如下:

-Dcom.sun.management.jmxremote
#指定 jvm 所在伺服器 ip 或域名
-Djava.rmi.server.hostname=192.168.1.1
#指定埠
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.rmi.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
相關閱讀:

Java 記憶體模型簡介

無意中就做了個 web 版 JVM 監控端

Java-agent, 除錯工具、熱部署、JVM 監控工具都用到了它

不要吝惜你的「推薦」呦

歡迎關注,不定期更新本系列和其他文章
古時的風箏 ,進入公眾號可以加入交流群

相關推薦

JVM 不得不知一些引數

有的同學雖然寫了一段時間 Java 了,但是對於 JVM 卻不太關注。有的同學說,引數都是團隊規定好的,部署的時候也不用我動手,關注它有什麼用,而且,JVM 這東西,聽上去就感覺很神祕很高深的樣子,還是算了吧。 沒錯,部署的時候可能用不到你親自動手,但是出現問題了怎麼辦,難道不用你解決問題嗎,如果對 JVM

TCP/IP不得不知的十大秘密

比特 smt 鏈路 復數 增長 超過 工具 地址解析 gmp 這段時間 有一點心很浮躁,不過希望自己馬上要矯正過來。好好學習編程!這段時間我想好好地研究一下TCP/IP協議和網絡傳輸這塊!加油 一、TCP/IP模型 TCP/IP協議模型(Transmission Con

每個專案不得不知的11個Java第三方類庫

單元測試 DBunit是一個基於junit擴充套件的資料庫測試框架。它提供了大量的類對與資料庫相關的操作進行了抽象和封裝。 Mockito是一個針對Java的mocking框架。你可以使用簡潔的API編寫出漂亮的測試。 Hamcrest 是一個測試輔助工

細數不得不知的容器安全工具

docker 工具 網絡安全 鏡像 引擎 容器 網絡安全問題的重要性大概毋庸置疑,最近無數關於惡意軟件和安全漏洞的消息已充分證明了這一點。假如你要管理一個Docker環境,並希望幫助自己的公司或用戶在下一個大漏洞來臨時避免遇到麻煩,那麽你就需要了解一些保障Docker應用安全的工具,並

做用戶體驗設計,不得不知的18件事

以下內容由Mockplus團隊翻譯整理,僅供學習交流,Mockplus是更快更簡單的原型設計工具。 沒有人會告訴你的設計小竅門 我在40歲的時後改變了我的職業生涯,成為了一名UX設計師。2014年,我在澳大利亞悉尼完成了一個為期3個月的UX設計課程。課程完成後,我仍然有很多東西要

OCR----不得不知的Tesseract六大重要核心

Abstract 整理了很多OCR的資料,這篇主要是對Tesseract重要的知識進行總結羅列。本次總結,基於2007年Smith所寫的Paper—-《An Overview of the Tesseract OCR Engine》,所以算是論文導讀吧。PS:Smith是一個專

C語言之不得不知的指標(二)

 C語言之你不得不知的指標(二)         指標是一個地址,指標變數是存放地址的變數。通過下面這幾段程式可以很好的理解指標和指標變數。              

C語言之不得不知的陣列(一)

1、強制型別轉換運算子:     (double)a --------------------(將a轉換為double型別)     (int)(x+y)-------------------(將x+y的值轉換為int型別)   &n

Kubernetes 1.5有哪些不得不知的新功能?_Kubernetes中文社群

今年9月份我們迎來了Kubernetes 1.4的驚喜釋出,一大波新功能讓人眼花繚亂。經過將近三個月時間的打磨,如今Kubernetes再推出新版本,翹首以盼的Kubernetes 1.5重磅釋出,本次版本更新涵蓋了4個主題、12個新特性以及4個原有基礎上的重大變更。期待不如眼疾手快,翻閱文章

如果喜歡Python 那麼不得不知的幾個開源專案

1.Trac Trac擁有強大的bug管理 功能,並集成了Wiki 用於文件管理。它還支援程式碼管理工具Subversion ,這樣可以在 bug管理和Wiki中方便地參考程式原始碼。 Trac有著比較強大的外掛系統,可以通過外掛來實現各種各樣的功能,比如支援G

揭祕“風水界”不得不知的那些事

  風水師大家都不“麥勝”吧!古往今來都有相關記載,看個風水、選個陰宅那是“小菜一碟”。不管是哪路“神仙”都自稱是可以逢凶化吉的“風水大師”,其實不然。 風水師在宋代比較盛行,到明清就變得氾濫,看似在我國解放理論時期的影響下受到了“重創”,但實際中還在不斷運用,到目前為止,

有趣!10個不得不知的Linux終端遊戲

關注「實驗樓」,每天分享一個專案教程   Linux 終端在多數人眼中,是一個非常單調和無聊的工

JVM堆空間劃分、引數設定

上圖中,刻畫了Java程式執行時的堆空間,可以簡述成如下2條 1.JVM中堆空間可以分成三個大區,新生代、老年代、永久代 2.新生代可以劃分為三個區,Eden區,兩個倖存區 在JVM執行時,可以通過配置以下引數改變整個JVM堆的配置比例 1.JVM執行時堆的大小  

不得不知的邏輯或(||)與(&&)非(!)

       最近重新翻開原生JS,又得到很多不同的體會,雖然現在開發框架那麼多,但很多思想都還是離不開原生的基礎。今天呢,我就根據自己的學習總結一下邏輯與(&&)和(邏輯或(||)和邏輯非(!)。       基本定義       ||:邏輯或,只有表示式的值都為false,才返回false

12種不得不知的Android除錯方式

1. 檢視當前堆疊1) 功能:在程式中加入程式碼,使可以在logcat中看到打印出的當前函式呼叫關係2) 方法: new Exception(“print trace”).printStackTrace();2. MethodTracing1) 功能:用於熱點分析和效能優化,分析每個函式佔用的CPU時間,呼叫

php的curl的一些引數總結

curl可以根據是否是http或則是https選擇加密傳送的內容; 使用curl傳送請求的基本流程 1,初始化連線控制代碼; 2,設定curl選項; 3,執行並獲取結果; 4,釋放curl連線控制代碼; 例子: //初始化 $ch = curl_init(); //設定選項

jinjafor迴圈的一些引數介紹

在python中使用jinjia模版遍歷資料的時候,一些常用的屬性 變數 描述 loop.index 當前迭代索引(從1開始) loop.index()

前端開發:這10個Chrome擴充套件不得不知

轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 原文出處:https://blog.bitsrc.io/10-top-chrome-extensions-for-front-end-developers-db23a01dce1e 1. CSSViewer &nb

電腦科學之演算法——不得不知的遞迴

# 遞迴 >本系列文章在Github:[StevenEco](https://github.com/StevenEco/ComputerScience)以及[WarrenRyan](https://www.cnblogs.com/warrenryan)同步更新 ## 簡介 程式呼叫自身的程式設計技巧稱為

升級Kubernetes 1.18前,不得不知的9件事

本文來自Rancher Labs 昨天Kubernetes最新版本v1.18已經發布,其包含了38項功能增強,其中15項為穩定版功能、11項beta版功能以及12項alpha版功能。在本文中,我們將探索其中一些功能,希望能幫助你決定是否需要升級。那麼,我們現在開始吧! 將Service Account T