老生常談,面試吹牛的的最佳談資,在接下來的幾天裏,我找了點資料來對其進行一波學習;html
本地環境是不須要對咱們的虛擬機進行優化的,通常在生產環境下,也就是Linux下才有對JVM優化的需求java
在JVM中有不少的參數是能夠設置的,這些參數咱們把它分爲三類面試
標準參數(比較穩定的,在將來的版本更迭中,都不會丟失的,非標準的參數不能保證)sql
-X參數(也就是非標準的 java -X 查看全部的參數)數組
-XX參數(也是非標準參數,這種類型的參數通常都是用於JVM的調優改動)tomcat
java -help:查看命令,咱們能夠在裏面找到上面所說的三種類型的的影子jvm
java -version :查看jvm的版本工具
java -showversion :查看kvm版本信息,並執行其後的其餘命令(經常使用)學習
-D:設置系統參數,至關於上下文,咱們能夠添加K和V進去,而後拿到K的值測試
首先咱們去Linux上寫一個測試類以下所示:
而後咱們去編譯並運行它:
可見是沒有值的,下面咱們就對「chen」這個K,設置Value,讓他被獲取到:
java -Dchen=HelloWorld test1:意思爲設置系統屬性」chen「,爲其賦值爲HelloWorld,而後再運行test1文件,
最後輸出結果已經能夠發現,系統屬性設置生效
-server 和 -client 模式
server模式的話,jvm的初始化堆空間會大一些,啓動慢,可是後續的運行就很是的絲滑
client模式的話,jvm初始化的堆空間就會小一點,啓動很是快,可是運行相對較卡
這個都是瞭解部分,覺得jvm在啓動的時候會根據硬件和系統自動給我選擇最合適的模式
如今的機器基本都是64位的系統吧,64位的系統只支持server模型,只要機器給力都是選擇server模式
咱們能夠經過java -X 這個命令去獲取全部-x的參數列表
-Xms和-Xmx參數設置堆內存的初始化大小和最大大小
-Xmx2048m:表示設置JVM的最大堆內存爲2048兆
-Xms512m:表示設置JVM的初始化堆內存爲512兆
-Xint、-Xcomp、-Xmixed,這三個參數的配置
-Xint,解釋模式,會強制jvm逐行執行全部的字節碼,運行速度很明顯的變慢
-Xcomp,編譯模式,jvm在第一次使用時會把全部的字節碼編譯成本地代碼(會卡一下),帶來最大的優化效果
-Xmixed,混合模式,將解釋模式與編譯模式進行混合使用,由jvm本身決定,默認使用該模式
編譯模式下會卡頓一下再彈出結果,這個值得注意一下,但這也是一種優化,後面執行就會很是流暢
上面已經說到,-XX也是非標準參數,主要用於jvm的調優和debug的操做
-XX參數的使用分爲兩種方式,一種boolean類型,一種非boolean類型
boolean類型
-XX[+/-]<name> :表示啓動或者禁用某個屬性,+:啓動,-:禁用
如:-XX:+DisableExplicitGC:表示開啓禁用手動調用gc操做,也就是說System.gc無效
非boolean類型
-XX:<name>=<value> :表示name的值爲Value
如:-XX:NewRatio=1 :表示新生代和老年代的比值
運行Java命令時打印出運行參數
執行:java -XX:+PrintFlagsFinal test1
會獲得一堆信息配置的信息,大部分的信息咱們都看不懂,但仍是有一點須要說明
在咱們獲得的信息列表中都是KV結構的,V通常分爲true/false或者爲屬性值這兩種方式
k=V,這種經過=符號表示的,是使用的默認值
k:=V,這種方式表示已經被咱們改動,是使用的咱們給定的參數
查看正在運行的java進程的參數
啓動一個tomcatu用於測試,下面咱們經過jinfo命令查看全部的運行參數信息
jinfo -flags <進程id>:進程ID,咱們能夠經過ps -ef | grep tomcat 拿到,下面咱們一塊兒來看看
經過上面這張體,能夠發現,不少參數被被打印了,雖然咱們大部分都不知道他的意思,但咱們仔細讀讀仍是有那麼兩個咱們在上面講過的
若是咱們只想單一的查看某個運行參數的值,咱們能夠經過下面這種方式獲取:
jinfo -flag <參數名稱> <進程id>,好比咱們去獲取最大的堆內存空間大小:
你也能夠 :回顧往日學習:jvm內存模型
首先咱們須要知道的是,瞭解JVM的內存模型對於JVM調優有什麼幫助?
[JDK1.7] :年輕帶——老年代——永久代 (統一被JVM虛擬機管理)
[JDK1.8]: 年輕帶——老年代——元空間(元空間被操做系統本地內存內管理)
整體上劃分爲了三個板塊,每一個板塊中都會再進行細度劃分,但都有一個伸縮區的存在,且佔有大量內存空間
咱們在JVM內存模型中的優化主要就是針對這個伸縮區的大小進行根據項目進行調整,實現優化效果
jdk1.8的內存模型:
【年輕代】:被細分爲三個區域[Eden區、兩個大小嚴格相同的Survivor區、伸縮區]
Eden區用於存放剛剛建立的對象,空間佔滿了就會觸發GC,有些對象在GC後仍然保留了下來,進入存活區
存活取有兩個嚴格相同大小的空間,某一時刻,只有一個是在被使用的,好比圖中的S0用來存放Eden過來的對象
當S0空間不足,觸發GC時,就會把仍然存活的對象複製到S1,而後把S0的內存空間給刷掉
根據JVM的策略,再存活取通過幾回GC後,而後存在的對象就會被存放到老年代中去
【老年代】:被細分爲 [舊生代、伸縮區]
主要保存生命週期較長的對象,用於分撒年輕的儲存壓力
當我建立的是一個比較大的對象時,會跳過年輕帶直接進入老年代儲存
【元空間】:替換了1.7中的永久代,被細分爲[CCS、CodeCache]
CodeCache:存放類,class等數據
CCS:類的壓縮指針,默認不開啓,不作使用
【伸縮區 Virtual區】:最大內存和初始內存的差值,就是伸縮區,這就是咱們優化的目標所在
爲何廢除1.7的永久代和使用寄存在本地內存中的元空間
由於永久代內存常常不夠用且有發生內存泄漏的隱患,爆出內存空間不足的錯誤
基於此,將永久代廢棄,採用基於本地內存空間的元空間
jstat:能夠查看堆內存中各部分的使用量,以及加載類的數量
格式:jstat -命令現象 進程id 運用以下所示
Loaded:Tomcat啓動一共加載的class數量
Bytes:所佔用的空間大小
Unloaded:未加載數量
Bytes:未加載佔用空間大小
Time:加載所耗時間
Compiled:編譯數量
Failed:失敗數量
Invalid:不可用數量
Time:編譯所耗時間
FailedType:失敗類型
FailedMethod:失敗的方法
咱們能夠經過使用 jstat -gc 2310 1000 5
這種命令來屢次查看,好比上面這個命令的意思爲:一秒執行一次,一共執行五次
眼睛都給我看瞎了,臥槽!
soc:第一個 Survivor區的大小
s1c:第二個 Survivor區的大小(嚴格規定大小一致)
s0u:第一個 Survivor區的使用大小
s1u:第二個 Survivor區的使用大小
EC:Eden區的大小(KB)
OC:Old區大小(KB)
OU:Old使用大小
MC:方法區大小(KB)
MU:方法區使用大小
CCSC:壓縮類空間大小(KB)
CCSU:壓縮類空間使用大小
YGC:年輕代垃圾回收次數
YGCT:年輕代垃圾回收消耗時間
FGC:老年代垃圾回收次數
jmap相比jstat能夠獲取到更多詳細的數據
jmap -heap 進程id,以下所示
jmap -histo 2310 | more :查看全部對象,包括活躍以及非活躍對象的相關信息
jmap-histo:live 2310 | more :查看活躍的對象詳細
其餘你不認識,String總該認識吧。經過上面的命令,咱們知道String在Tomcat這個進程中一共建立了31768個對象,佔用內存762432K大小,至於其餘的讓咱們慢慢寫來
B :byte
C:char
D:double
F:float
I: int
J: long
Z: boolean
[ :數組,能夠上面配合使用
[L + 類名 :其餘對象
可見,byte數組建立的UI底下那個不是最多的,可是所佔用的內存開銷確是最大的
什麼意思呢?dump:轉儲
也就是將咱們的內存的使用狀況輸出到文件中,而後咱們對其進行分析
jmap -dump:format=b,file=指定轉儲文件絕對路徑 進程id
上面咱們已經經過dump命令,將咱們的Tomcat的 內存使用狀況轉儲到了本地dump.dat文件中
下面咱們經過jhat對該文件進行分析,jhat用法以下:jhat -port 自定義端口號 dump文件絕對路徑
上面能夠看到,我本地已經對其進行了訪問,每一個對象都是以包的方式集結在一塊兒,因此若是想要看咱們本身寫的代碼的話,去找包就能找到,點擊進去我發現個人功力還不夠,看不出什麼名堂來,
下面講另外一個東西,咱們直接網頁翻到最底部:最後一行數據:[Execute Object Query Language (OQL) query]
OQL:這是一種檢索語言,有點像sql,咱們點進去,查看相關的幫助文檔:
測試一把,咱們調整檢索條件? 把字符長度調整到1W去,再次檢索
能夠發現,不少都是配置文件,Tomcat內部將配置文件讀取後賦值給了一個String對象