日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

JVM优化之优化常用参数和工具

發(fā)布時(shí)間:2023/12/19 综合教程 26 生活家
生活随笔 收集整理的這篇文章主要介紹了 JVM优化之优化常用参数和工具 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

JVM優(yōu)化之優(yōu)化常用參數(shù)和工具


內(nèi)容提要

  • jvm運(yùn)行參數(shù)和參數(shù)設(shè)置
  • jvm 內(nèi)存模型
  • 定位分析死鎖和內(nèi)存溢出
  • 其他工具使用

為什么要優(yōu)化JVM
1.生產(chǎn)環(huán)境需要承載更多的并發(fā)要求,對(duì)底層的優(yōu)化能顯著提升性能,節(jié)約成本
2.測(cè)試和生產(chǎn)環(huán)境的不同可能導(dǎo)致我們無法實(shí)時(shí)了解具體性能問題,我們需要借助對(duì)JVM了解分析問題所在。

jvm運(yùn)行參數(shù)和參數(shù)設(shè)置

1.標(biāo)準(zhǔn)參數(shù)

由java -help檢索出來的所有參數(shù)成為標(biāo)準(zhǔn)參數(shù),未來發(fā)行版本中不會(huì)輕易修改,即使修改也會(huì)有官方通知

 	>java -help
	-java [-options] class [args...] (執(zhí)行類)或 java [-options] -jar jarfile [args...] #(執(zhí)行 jar 文件)其中選項(xiàng)包括:
	-D<名稱>=<值> #設(shè)置系統(tǒng)屬性
	-version #輸出產(chǎn)品版本并退出
	-showversion # 輸出產(chǎn)品版本并繼續(xù)
	-? -help 輸出此幫助消息
	-X  #輸出非標(biāo)準(zhǔn)選項(xiàng)的幫助
	-d32 #使用 32 位數(shù)據(jù)模型 (如果可用)
	-d64 #使用 64 位數(shù)據(jù)模型 (如果可用)
	-server #選擇 "server" VM 默認(rèn) VM 是 server,因?yàn)槟窃诜?wù)器類計(jì)算機(jī)上運(yùn)行。
	-cp <目錄和 zip/jar 文件的類搜索路徑>
	-classpath <目錄和 zip/jar 文件的類搜索路徑> #用 : 分隔的目錄, JAR 檔案和 ZIP 檔案列表, 用于搜索類文件。
    ###########################以上為非常重要的參數(shù) 希望開發(fā)者一定要記住###########################

	-verbose:[class|gc|jni] #啟用詳細(xì)輸出
	-version:<值> #警告: 此功能已過時(shí), 將在未來發(fā)行版中刪除。需要指定的版本才能運(yùn)行
	
	-jre-restrict-search | -no-jre-restrict-search #警告: 此功能已過時(shí), 將在未來發(fā)行版中刪除。在版本搜索中包括/排除用戶專用 JRE
	-ea[:<packagename>...|:<classname>]
	-enableassertions[:<packagename>...|:<classname>]#按指定的粒度啟用斷言
	-da[:<packagename>...|:<classname>]
	-disableassertions[:<packagename>...|:<classname>] #禁用具有指定粒度的斷言
	-esa | -enablesystemassertions # 啟用系統(tǒng)斷言
	-dsa | -disablesystemassertions # 禁用系統(tǒng)斷言
	-agentlib:<libname>[=<選項(xiàng)>] #加載本機(jī)代理庫(kù) <libname>, 例如 -agentlib:hprof另請(qǐng)參閱 -agentlib:jdwp=help 和 -agentlib:hprof=help
	-agentpath:<pathname>[=<選項(xiàng)>] #按完整路徑名加載本機(jī)代理庫(kù)
	-javaagent:<jarpath>[=<選項(xiàng)>] #加載 Java 編程語(yǔ)言代理, 請(qǐng)參閱 java.lang.instrument
	-splash:<imagepath> # 使用指定的圖像顯示啟動(dòng)屏幕

使用Java代碼測(cè)試系統(tǒng)屬性

	Properties properties = System.getProperties();
	for (Map.Entry<Object, Object> objectObjectEntry : properties.entrySet()) { 
   
		System.out.printf("system prop : %s = %s\n",objectObjectEntry.getKey(),objectObjectEntry.getValue());
	}
// java -Dmyname=huyiyu [類名] 之后在打印所有系統(tǒng)參數(shù)中找到myname=huyiyu

server和client參數(shù)

server: 顯式指定-server時(shí)設(shè)置,或者64位系統(tǒng)時(shí)設(shè)置,使用 parNew GC 1 啟動(dòng)慢運(yùn)行快
client:顯式指定-client時(shí)設(shè)置,或者64位系統(tǒng)時(shí)設(shè)置,使用default GC2啟動(dòng)快運(yùn)行慢
系統(tǒng)信息如下:

windowsX86 其他X86 其他X86 Mem:>2GB >2CPU X64
client client server server

2.非標(biāo)準(zhǔn)參數(shù)

-Xmixed # 混合模式執(zhí)行 (默認(rèn))
-Xint #僅解釋模式執(zhí)行
-Xbatch #禁用后臺(tái)編譯
-Xms<size> #設(shè)置初始 Java 堆大小
-Xmx<size> #設(shè)置最大 Java 堆大小
-Xss<size> #設(shè)置 Java 線程堆棧大小
-XshowSettings #顯示所有設(shè)置并繼續(xù)
########################以上參數(shù)非常重要需要記住###############################
-XshowSettings:all#顯示所有設(shè)置并繼續(xù)
-XshowSettings:vm 顯示所有與 vm 相關(guān)的設(shè)置并繼續(xù)
-XshowSettings:properties #顯示所有屬性設(shè)置并繼續(xù)
-XshowSettings:locale#顯示所有與區(qū)域設(shè)置相關(guān)的設(shè)置并繼續(xù)
-Xbootclasspath: <用 : 分隔的目錄和 zip/jar 文件> #設(shè)置搜索路徑以引導(dǎo)類和資源
-Xbootclasspath/a:<用 : 分隔的目錄和 zip/jar 文件>#附加在引導(dǎo)類路徑末尾
-Xbootclasspath/p:<用 : 分隔的目錄和 zip/jar 文件>#置于引導(dǎo)類路徑之前
-Xdiag #顯示附加診斷消息
-Xnoclassgc #禁用類垃圾收集
-Xincgc #啟用增量垃圾收集
-Xloggc:<file> #將 GC 狀態(tài)記錄在文件中 (帶時(shí)間戳)
-Xprof #輸出 cpu 配置文件數(shù)據(jù)
-Xfuture #啟用最嚴(yán)格的檢查, 預(yù)期將來的默認(rèn)值
-Xrs #減少 Java/VM 對(duì)操作系統(tǒng)信號(hào)的使用 (請(qǐng)參閱文檔)
-Xcheck:jni #對(duì) JNI 函數(shù)執(zhí)行其他檢查
-Xshare:off #不嘗試使用共享類數(shù)據(jù)
-Xshare:auto #在可能的情況下使用共享類數(shù)據(jù) (默認(rèn))
-Xshare:on #要求使用共享類數(shù)據(jù), 否則將失敗。
#-X 選項(xiàng)是非標(biāo)準(zhǔn)選項(xiàng), 如有更改, 恕不另行通知。

設(shè)置編譯模式

類型 說明 示例 用法 備注
int 解釋模式 -Xint -Xint 強(qiáng)制運(yùn)行字節(jié)碼,效率低
comp 編譯模式 -Xcomp -Xcomp 編譯成native代碼帶來大程度的優(yōu)化
mix 混合模式 -Xmix -Xmix 解釋和編譯混合進(jìn)行,由jvm決定使用任意推薦使用

設(shè)置初始堆內(nèi)存

類型 說明 示例 用法 備注
Xms 最小堆內(nèi)存 -Xms<數(shù)字><單位> -Xmx1024m 設(shè)置最小堆內(nèi)存為1024MB
Xmx 最大堆內(nèi)存 -Xmx<數(shù)字><單位> -Xms1024m 設(shè)置最大堆內(nèi)存為1024MB
Xss 初始堆內(nèi)存 -Xmx<數(shù)字><單位> -Xss1024m 設(shè)置初始堆內(nèi)存為1024MB

XX參數(shù)

XX參數(shù)也是非標(biāo)準(zhǔn)參數(shù),用于jvm調(diào)優(yōu)和debug操作,設(shè)置JVM有兩種模式分別如下

類型 用法 示例 備注
boolean -XX:+/-<name> XX:+DisableExplicitGC +:啟用 -:禁用
非boolean :-XX:<name>=<value> :-XX:NewRatio=1
# XX參數(shù)實(shí)戰(zhàn)
-XX:+PrintFlagsFinal -version
	# =表示默認(rèn)參數(shù) :=表示重置生效參數(shù)
     bool UseXMMForArrayCopy                       = true                                      { 
   product} { 
   default}
     bool UseXMMForObjInit                         = false                                { 
   ARCH product} { 
   default}
     bool UseXmmI2D                                = false                                { 
   ARCH product} { 
   default}
     bool UseXmmI2F                                = false                                { 
   ARCH product} { 
   default}
     bool UseXmmLoadAndClearUpper                  = true                                 { 
   ARCH product} { 
   default}
     bool UseXmmRegToRegMoveAll                    = true                                 { 
   ARCH product} { 
   default}
     bool VMThreadHintNoPreempt                    = false                                     { 
   product} { 
   default}
     intx VMThreadPriority                         = -1                                        { 
   product} { 
   default}
     intx VMThreadStackSize                        = 0                                      { 
   pd product} { 
   default}
     intx ValueMapInitialSize                      = 11                                     { 
   C1 product} { 
   default}
     intx ValueMapMaxLoopSize                      = 8                                      { 
   C1 product} { 
   default}
     intx ValueSearchLimit                         = 1000                                   { 
   C2 product} { 
   default}
     bool VerifyMergedCPBytecodes                  = true                                      { 
   product} { 
   default}
     bool VerifySharedSpaces                       = false                                     { 
   product} { 
   default}
	...
# 使用jinfo可查看運(yùn)行的應(yīng)用的jvm參數(shù) :jinfo pid

jvm 內(nèi)存模型

JDK1.7 jvm內(nèi)存模型

jdk7 jvm 堆模型

  • Young 年輕區(qū)

Young區(qū)被劃分為三部分,Eden區(qū)和兩個(gè)大小嚴(yán)格相同的Survivor區(qū),其中,Survivor區(qū)間中,某一時(shí)刻只有
其中一個(gè)是被使用的,另外一個(gè)留做垃圾收集時(shí)復(fù)制對(duì)象用,在Eden區(qū)間變滿的時(shí)候, GC就會(huì)將存活的對(duì)
象移到空閑的Survivor區(qū)間中,根據(jù)JVM的策略,在經(jīng)過幾次垃圾收集后,任然存活于Survivor的對(duì)象將被移
動(dòng)到Tenured區(qū)間。

  • Tenured 年老區(qū)

Tenured區(qū)主要保存生命周期長(zhǎng)的對(duì)象,一般是一些老的對(duì)象,當(dāng)一些對(duì)象在Young復(fù)制轉(zhuǎn)移一定的次數(shù)以
后,對(duì)象就會(huì)被轉(zhuǎn)移到Tenured區(qū),一般如果系統(tǒng)中用了application級(jí)別的緩存,緩存中的對(duì)象往往會(huì)被轉(zhuǎn)
移到這一區(qū)間。

  • Perm 永久區(qū)

Perm代主要保存class,method,filed對(duì)象,這部份的空間一般不會(huì)溢出,除非一次性加載了很多的類,不過在
涉及到熱部署的應(yīng)用服務(wù)器的時(shí)候,有時(shí)候會(huì)遇到j(luò)ava.lang.OutOfMemoryError : PermGen space 的錯(cuò)誤,
造成這個(gè)錯(cuò)誤的很大原因就有可能是每次都重新部署,但是重新部署后,類的class沒有被卸載掉,這樣就造
成了大量的class對(duì)象保存在了perm中,這種情況下,一般重新啟動(dòng)應(yīng)用服務(wù)器可以解決問題。

  • Virtual區(qū)

最大內(nèi)存和初始內(nèi)存的差值,就是Virtual區(qū)。

JDK1.8內(nèi)存模型

JDK1.8的堆內(nèi)存模型

由上圖可以看出,jdk1.8的內(nèi)存模型是由2部分組成,年輕代 + 年老代。
年輕代:Eden + 2*Survivor
年老代:OldGen
在jdk1.8中變化最大的Perm區(qū),用Metaspace(元數(shù)據(jù)空間)進(jìn)行了替換。
需要特別說明的是:Metaspace所占用的內(nèi)存空間不是在虛擬機(jī)內(nèi)部,而是在本地內(nèi)存空間中,這也是與1.7的永
久代最大的區(qū)別所在。

JDK1.8廢棄永久區(qū)的原因

This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need
to configure the permanent generation (since JRockit does not have a permanent
generation) and are accustomed to not configuring the permanent generation.
移除永久代是為融合HotSpot JVM與 JRockit VM而做出的努力,因?yàn)镴Rockit沒有永久代,不需要配置永久代。
現(xiàn)實(shí)使用中,由于永久代內(nèi)存經(jīng)常不夠用或發(fā)生內(nèi)存泄露,爆出異常java.lang.OutOfMemoryError: PermGen。
基于此,將永久區(qū)廢棄,而改用元空間,改為了使用本地內(nèi)存空間。

定位分析死鎖和內(nèi)存溢出

定位死鎖

//以下是一段死鎖代碼
package com.yiyu;

public class DeadLock { 
   
    private static final String LOCK_A = "LOCK_A";
    private static final String LOCK_B = "LOCK_B";
    public static void main(String[] args) throws InterruptedException { 
   
        Thread thread1 = new Thread(() -> DeadLock.getLock("thread_1", LOCK_A, LOCK_B));
        Thread thread2 = new Thread(() -> DeadLock.getLock("thread_2", LOCK_B, LOCK_A));
        thread1.start();
        thread2.start();
    }

    public static void getLock(String user, String lock1, String lock2) { 
   
        try { 
   
            synchronized (lock1) { 
   
                System.out.println(user + "獲得了" + lock1 + "的鎖");
                synchronized (lock2) { 
   
                    System.out.println(user + "獲得了" + lock2 + "的鎖");
                }
            }
        } catch (Exception e) { 
   
            e.printStackTrace();
        }
    }
}
# 使用jps查看進(jìn)程ID
[root@izwz92w1juq9pnt03ae87yz ~]# jps 
10400 Bootstrap
12812 Jps
12733 DeadLock
[root@izwz92w1juq9pnt03ae87yz ~]# jstack 12733
...
Found one Java-level deadlock:
=============================
"Thread-0":
waiting to lock monitor 0x00007fa788008900 (object 0x00000000e34c2258, a java.lang.String),
which is held by "Thread-1"
"Thread-1":
waiting to lock monitor 0x00007fa788006900 (object 0x00000000e34c2228, a java.lang.String),
which is held by "Thread-0"
Java stack information for the threads listed above:
===================================================
"Thread-0":
at DeadLock.getLock(DeadLock.java:17)
- waiting to lock <0x00000000e34c2258> (a java.lang.String)
- locked <0x00000000e34c2228> (a java.lang.String)
at DeadLock.lambda$main$0(DeadLock.java:6)
at DeadLock$$Lambda$1/0x0000000100060840.run(Unknown Source)
at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)
"Thread-1":
at DeadLock.getLock(DeadLock.java:17)
- waiting to lock <0x00000000e34c2228> (a java.lang.String)
- locked <0x00000000e34c2258> (a java.lang.String)
at DeadLock.lambda$main$1(DeadLock.java:7)
at DeadLock$$Lambda$2/0x0000000100062840.run(Unknown Source)
at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)
Found 1 deadlock.
"Thread-0" #10 prio=5 os_prio=0 cpu=22.94ms elapsed=369.77s tid=0x00007fa7a8156000 nid=0x31c9 waiting for monitor entry [0x00007fa79081b000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLock.getLock(DeadLock.java:17) #死鎖發(fā)生的代碼的行
- waiting to lock <0x00000000e34c2258> (a java.lang.String)
- locked <0x00000000e34c2228> (a java.lang.String)
at DeadLock.lambda$main$0(DeadLock.java:6)
at DeadLock$$Lambda$1/0x0000000100060840.run(Unknown Source)
at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)
"Thread-1" #11 prio=5 os_prio=0 cpu=23.86ms elapsed=369.77s tid=0x00007fa7a8157800 nid=0x31ca waiting for monitor entry [0x00007fa79071a000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLock.getLock(DeadLock.java:17)#死鎖發(fā)生的代碼的行
- waiting to lock <0x00000000e34c2228> (a java.lang.String)
- locked <0x00000000e34c2258> (a java.lang.String)
at DeadLock.lambda$main$1(DeadLock.java:7)
at DeadLock$$Lambda$2/0x0000000100062840.run(Unknown Source)

定位內(nèi)存溢出

package com.yiyu;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
public class OutOffMemoryErrorTest { 

public static void main(String[] args) { 

Stream.iterate(UUID.randomUUID()
.toString(), a -> a + a)
.limit(1000)
.reduce(String::concat)
.ifPresent(System.out::println);
}
}

java -Xmx6m -XX:+HeapDumpOnOutOfMemoryError OutOffMemoryErrorTest 程序運(yùn)行后會(huì)出現(xiàn)內(nèi)存溢出
具體如下:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid2176.hprof …
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
Heap dump file created [6383576 bytes in 0.029 secs]
at java.base/java.lang.String.concat(String.java:1947)
at com.yiyu.OutOffMemoryErrorTest$$Lambda$18/0x00000001000a8840.apply(Unknown Source)
at java.base/java.util.stream.ReduceOps$2ReducingSink.accept(ReduceOps.java:123)
at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:199)
at java.base/java.util.stream.Stream 1. t r y A d v a n c e ( S t r e a m . j a v a : 1231 ) a t j a v a . b a s e / j a v a . u t i l . s t r e a m . R e f e r e n c e P i p e l i n e . f o r E a c h W i t h C a n c e l ( R e f e r e n c e P i p e l i n e . j a v a : 127 ) a t j a v a . b a s e / j a v a . u t i l . s t r e a m . A b s t r a c t P i p e l i n e . c o p y I n t o W i t h C a n c e l ( A b s t r a c t P i p e l i n e . j a v a : 502 ) a t j a v a . b a s e / j a v a . u t i l . s t r e a m . A b s t r a c t P i p e l i n e . c o p y I n t o ( A b s t r a c t P i p e l i n e . j a v a : 488 ) a t j a v a . b a s e / j a v a . u t i l . s t r e a m . A b s t r a c t P i p e l i n e . w r a p A n d C o p y I n t o ( A b s t r a c t P i p e l i n e . j a v a : 474 ) a t j a v a . b a s e / j a v a . u t i l . s t r e a m . R e d u c e O p s 1.tryAdvance(Stream.java:1231) at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127) at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ReduceOps 1.tryAdvance(Stream.java:1231)atjava.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)atjava.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)atjava.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)atjava.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)atjava.base/java.util.stream.ReduceOpsReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:558)
at com.yiyu.OutOffMemoryErrorTest.main(OutOffMemoryErrorTest.java:14)
從項(xiàng)目中找到對(duì)應(yīng)的文件,使用工具分析

jvm其他工具使用

請(qǐng)參考博客jvm分析工具概述,對(duì)每個(gè)命令的每個(gè)操作分析的非常全面,跳轉(zhuǎn)方便以后閱讀。

JMX配置

原理是啟動(dòng)Java程序時(shí)添加系統(tǒng)參數(shù)已達(dá)到暴露端口提供接入虛擬機(jī)的協(xié)議,網(wǎng)上的配置非常詳細(xì)但是有些不足,使用JMX時(shí)會(huì)開放三個(gè)端口,如果僅僅開啟com.sun.management.jmxremote.port會(huì)發(fā)現(xiàn) Jconsole活visualVM仍然訪問不了,此時(shí) 使用netstat -nltp 查詢打開另外兩個(gè)端口或多一行配置即可,具體原因是因?yàn)镴MX支持本地連接建立的端口。如需知道更詳細(xì)信息請(qǐng)參考博客:JMX實(shí)踐-JMX連接端口

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false  
javax.management.remote.rmi.RMIConnectorServer=9999

  1. 并行垃圾收集器 部分stw ↩?

  2. 串行垃圾收集器單線程 全部stw ↩?

總結(jié)

以上是生活随笔為你收集整理的JVM优化之优化常用参数和工具的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。