JVM tuning goals: Use a smaller memory footprint to obtain higher throughput or lower latency.
Sometimes there will be some JVM problems, large and small, during testing or running of the program before going online, such as excessive CPU load, request delay, reduced tps, etc., and even memory leaks (used for each garbage collection) The time is getting longer and longer, the frequency of garbage collection is getting higher and higher, and the garbage data cleaned up by each garbage collection is getting smaller and smaller), memory overflow causes the system to crash, so the JVM needs to be tuned so that the program can run normally. to achieve higher user experience and operating efficiency.
Here are several important indicators:
Memory usage: The amount of memory required for the normal operation of the program.
Delay: Program pause time due to garbage collection.
Throughput: The ratio of the user program running time to the total time occupied by the user program and garbage collection.
Of course, just like the CAP principle, it is impossible to simultaneously satisfy a program’s small memory footprint, low latency, and high throughput. The goals of the program are different, and the direction to be considered when tuning is It is also different. Before tuning, you must combine the actual scenario, have clear optimization goals, find the performance bottleneck, optimize the bottleneck in a targeted manner, and finally conduct testing to confirm whether the tuning results meet the requirements through various monitoring tools. Target.
JVM Tuning Tool
(1) The data that tuning can rely on and refer to include system running logs, stack error messages, gc logs, thread snapshots, and heap transfers Store snapshots, etc.
① System operation log: The system operation log is the log printed in the program code, which describes the system operation track at the code level (execution method, input parameters, return value, etc.). Generally, there is a problem with the system. The system operation log is the first log to check.
② Stack error information: When an exception occurs in the system, the problem can be initially located based on the stack information. For example, based on "java.lang.OutOfMemoryError: Java heap space", it can be determined that it is a heap memory overflow; based on "java. "lang.StackOverflowError" can be judged to be a stack overflow; "java.lang.OutOfMemoryError: PermGen space" can be judged to be a method area overflow, etc.
③GC log: Use -XX: PrintGCDetails and -Xloggc:/data/jvm/gc.log when the program starts to record the detailed process of gc when the program is running, or directly configure "-verbose:gc "Parameter prints the gc log to the console. Through the recorded gc log, the frequency, time, etc. of gc in each memory area can be analyzed to find problems and perform targeted optimization.
For example, the following GC log:
2018-08-02T14:39:11.560-0800: 10.171: [GC [PSYoungGen: 30128K->4091K(30208K)] 51092K->50790K(98816K), 0.0140970 secs] [Times: user=0.02 sys=0.03, real=0.01 secs] 2018-08-02T14:39:11.574-0800: 10.185: [Full GC [PSYoungGen: 4091K->0K(30208K)] [ParOldGen: 46698K->50669K(68608K)] 50790K->50669K(98816K) [PSPermGen: 2635K->2634K(21504K)], 0.0160030 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] 2018-08-02T14:39:14.045-0800: 12.656: [GC [PSYoungGen: 14097K->4064K(30208K)] 64766K->64536K(98816K), 0.0117690 secs] [Times: user=0.02 sys=0.01, real=0.01 secs] 2018-08-02T14:39:14.057-0800: 12.668: [Full GC [PSYoungGen: 4064K->0K(30208K)] [ParOldGen: 60471K->401K(68608K)] 64536K->401K(98816K) [PSPermGen: 2634K->2634K(21504K)], 0.0102020 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
There are 4 GC logs in total. Looking at the first line of log, "2018-08-02T14:39:11.560-0800" is accurate. UTC universal standard time format at the millisecond level. Configuring the parameter "-XX: PrintGCDateStamps" can print out this timestamp following the gc log. "10.171" is the number of seconds that elapsed from the start of the JVM to the occurrence of gc. The "[GC" at the beginning of the first line of log text indicates that Stop-The-World did not occur in this GC (the user thread paused), and the "[Full GC" at the beginning of the second line of log text indicates that Stop-The-World occurred in this GC. World, so [GC and [Full GC] have nothing to do with the new generation and the old generation, but are related to the type of garbage collector. If you call System.gc() directly, [Full GC(System) will be displayed. The next "[PSYoungGen" and "[ParOldGen" represent the area where GC occurs. The specific name displayed is also related to the garbage collector. For example, "[PSYoungGen" here represents the Parallel Scavenge collector, and "[ParOldGen" represents the Serial Old collection. collector, in addition, the Serial collector displays "[DefNew", the ParNew collector displays "[ParNew", etc. The following "30128K->4091K (30208K)" indicates that after this gc, the memory usage space in this area has been reduced from 30128K to 4091K, and the total memory size is 30208K. "51092K->50790K(98816K), 0.0140970 secs" after the gc description of each area. After this garbage collection, the memory usage space of the entire heap memory was reduced from 51092K to 50790K, and the total space of the entire heap memory was 98816K. gc took 0.0140970 seconds.
④Thread snapshot: As the name implies, you can see the status of the thread at a certain moment according to the thread snapshot. When there may be request timeout, infinite loop, deadlock, etc. in the system, you can further determine based on the thread snapshot. question. By executing the "jstack pid" command that comes with the virtual machine, you can dump the snapshot information of the threads in the current process. There are many examples on the Internet for more detailed use and analysis. This article is already very long, so I won't go into details. , post a blog for reference: http://www.cnblogs.com/kongzhongqijing/articles/3630264.html
⑤ Heap dump snapshot: You can use "-XX: HeapDumpOnOutOfMemory" and " -XX:HeapDumpPath=/data/jvm/dumpfile.hprof", when a memory overflow occurs in the program, the memory snapshot at that time is dumped in the form of a file (you can also directly use the jmap command to dump the memory snapshot at any time when the program is running) ), and analyze the memory usage at that time afterwards.
(2)JVM tuning tool
①用 jps(JVM process Status)可以查看虛擬機(jī)啟動(dòng)的所有進(jìn)程、執(zhí)行主類的全名、JVM啟動(dòng)參數(shù),比如當(dāng)執(zhí)行了JPSTest類中的main方法后(main方法持續(xù)執(zhí)行),執(zhí)行 jps -l可看到下面的JPSTest類的pid為31354,加上-v參數(shù)還可以看到JVM啟動(dòng)參數(shù)。
3265 32914 sun.tools.jps.Jps 31353 org.jetbrains.jps.cmdline.Launcher 31354 com.danny.test.code.jvm.JPSTest 380
②用jstat(JVM Statistics Monitoring Tool)監(jiān)視虛擬機(jī)信息
jstat -gc pid 500 10 :每500毫秒打印一次Java堆狀況(各個(gè)區(qū)的容量、使用容量、gc時(shí)間等信息),打印10次
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 11264.0 11264.0 11202.7 0.0 11776.0 1154.3 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 11202.7 0.0 11776.0 4037.0 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 11202.7 0.0 11776.0 6604.5 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 11202.7 0.0 11776.0 9487.2 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 0.0 0.0 11776.0 258.1 68608.0 58983.4 - - - - 15 0.082 8 0.059 0.141 11264.0 11264.0 0.0 0.0 11776.0 3076.8 68608.0 58983.4 - - - - 15 0.082 8 0.059 0.141 11264.0 11264.0 0.0 0.0 11776.0 0.0 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149 11264.0 11264.0 0.0 0.0 11776.0 0.0 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149 11264.0 11264.0 0.0 0.0 11776.0 258.1 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149 11264.0 11264.0 0.0 0.0 11776.0 3012.8 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149
jstat還可以以其他角度監(jiān)視各區(qū)內(nèi)存大小、監(jiān)視類裝載信息等,具體可以google jstat的詳細(xì)用法。
③用jmap(Memory Map for Java)查看堆內(nèi)存信息
執(zhí)行jmap -histo pid可以打印出當(dāng)前堆中所有每個(gè)類的實(shí)例數(shù)量和內(nèi)存占用,如下,class name是每個(gè)類的類名([B是byte類型,[C是char類型,[I是int類型),bytes是這個(gè)類的所有示例占用內(nèi)存大小,instances是這個(gè)類的實(shí)例數(shù)量:
num #instances #bytes class name ---------------------------------------------- 1: 2291 29274080 [B 2: 15252 1961040 <methodKlass> 3: 15252 1871400 <constMethodKlass> 4: 18038 721520 java.util.TreeMap$Entry 5: 6182 530088 [C 6: 11391 273384 java.lang.Long 7: 5576 267648 java.util.TreeMap 8: 50 155872 [I 9: 6124 146976 java.lang.String 10: 3330 133200 java.util.LinkedHashMap$Entry 11: 5544 133056 javax.management.openmbean.CompositeDataSupport
執(zhí)行 jmap -dump 可以轉(zhuǎn)儲(chǔ)堆內(nèi)存快照到指定文件,比如執(zhí)行 jmap -dump:format=b,file=/data/jvm/dumpfile_jmap.hprof 3361 可以把當(dāng)前堆內(nèi)存的快照轉(zhuǎn)儲(chǔ)到dumpfile_jmap.hprof文件中,然后可以對(duì)內(nèi)存快照進(jìn)行分析。
④利用jconsole、jvisualvm分析內(nèi)存信息(各個(gè)區(qū)如Eden、Survivor、Old等內(nèi)存變化情況),如果查看的是遠(yuǎn)程服務(wù)器的JVM,程序啟動(dòng)需要加上如下參數(shù):
"-Dcom.sun.management.jmxremote=true" "-Djava.rmi.server.hostname=12.34.56.78" "-Dcom.sun.management.jmxremote.port=18181" "-Dcom.sun.management.jmxremote.authenticate=false" "-Dcom.sun.management.jmxremote.ssl=false"
下圖是jconsole界面,概覽選項(xiàng)可以觀測(cè)堆內(nèi)存使用量、線程數(shù)、類加載數(shù)和CPU占用率;內(nèi)存選項(xiàng)可以查看堆中各個(gè)區(qū)域的內(nèi)存使用量和左下角的詳細(xì)描述(內(nèi)存大小、GC情況等);線程選項(xiàng)可以查看當(dāng)前JVM加載的線程,查看每個(gè)線程的堆棧信息,還可以檢測(cè)死鎖;VM概要描述了虛擬機(jī)的各種詳細(xì)參數(shù)。(jconsole功能演示)
下圖是jvisualvm的界面,功能比jconsole略豐富一些,不過大部分功能都需要安裝插件。概述跟jconsole的VM概要差不多,描述的是jvm的詳細(xì)參數(shù)和程序啟動(dòng)參數(shù);監(jiān)視展示的和jconsole的概覽界面差不多(CPU、堆/方法區(qū)、類加載、線程);線程和jconsole的線程界面差不多;抽樣器可以展示當(dāng)前占用內(nèi)存的類的排行榜及其實(shí)例的個(gè)數(shù);Visual GC可以更豐富地展示當(dāng)前各個(gè)區(qū)域的內(nèi)存占用大小及歷史信息(下圖)。(jvisualvm功能演示)
⑤分析堆轉(zhuǎn)儲(chǔ)快照
前面說到配置了 “-XX:+HeapDumpOnOutOfMemory” 參數(shù)可以在程序發(fā)生內(nèi)存溢出時(shí)dump出當(dāng)前的內(nèi)存快照,也可以用jmap命令隨時(shí)dump出當(dāng)時(shí)內(nèi)存狀態(tài)的快照信息,dump的內(nèi)存快照一般是以.hprof為后綴的二進(jìn)制格式文件。
可以直接用 jhat(JVM Heap Analysis Tool) 命令來分析內(nèi)存快照,它的本質(zhì)實(shí)際上內(nèi)嵌了一個(gè)微型的服務(wù)器,可以通過瀏覽器來分析對(duì)應(yīng)的內(nèi)存快照,比如執(zhí)行 jhat -port 9810 -J-Xmx4G /data/jvm/dumpfile_jmap.hprof 表示以9810端口啟動(dòng) jhat 內(nèi)嵌的服務(wù)器:
Reading from /Users/dannyhoo/data/jvm/dumpfile_jmap.hprof... Dump file created Fri Aug 03 15:48:27 CST 2018 Snapshot read, resolving... Resolving 276472 objects... Chasing references, expect 55 dots....................................................... Eliminating duplicate references....................................................... Snapshot resolved. Started HTTP server on port 9810 Server is ready.
在控制臺(tái)可以看到服務(wù)器啟動(dòng)了,訪問?http://127.0.0.1:9810/?可以看到對(duì)快照中的每個(gè)類進(jìn)行分析的結(jié)果(界面略low),下圖是我隨便選擇了一個(gè)類的信息,有這個(gè)類的父類,加載這個(gè)類的類加載器和占用的空間大小,下面還有這個(gè)類的每個(gè)實(shí)例(References)及其內(nèi)存地址和大小,點(diǎn)進(jìn)去會(huì)顯示這個(gè)實(shí)例的一些成員變量等信息:?
jvisualvm也可以分析內(nèi)存快照,在jvisualvm菜單的“文件”-“裝入”,選擇堆內(nèi)存快照,快照中的信息就以圖形界面展示出來了,如下,主要可以查看每個(gè)類占用的空間、實(shí)例的數(shù)量和實(shí)例的詳情等:?
還有很多分析內(nèi)存快照的第三方工具,比如eclipse mat,它比jvisualvm功能更專業(yè),出了查看每個(gè)類及對(duì)應(yīng)實(shí)例占用的空間、數(shù)量,還可以查詢對(duì)象之間的調(diào)用鏈,可以查看某個(gè)實(shí)例到GC Root之間的鏈,等等??梢栽趀clipse中安裝mat插件,也可以下載獨(dú)立的版本(http://www.eclipse.org/mat/downloads.php?),我在mac上安裝后運(yùn)行起來老卡死~下面是在windows上的截圖(MAT功能演示):
(3) JVM tuning experience
In terms of JVM configuration, in general, you can use the default configuration first (some basic initial parameters can ensure that general applications run more stably). During the test, according to the system Operating status (session concurrency, session time, etc.), combined with gc logs, memory monitoring, garbage collectors used, etc., make reasonable adjustments. When the old generation memory is too small, it may cause frequent Full GC. When the memory is too large, the Full GC time It will be extremely long.
So what is the most appropriate JVM configuration, such as the new generation and old generation? The answer is not necessarily. Tuning is the process of finding the answer. When the physical memory is certain, the larger the new generation setting, the smaller the old generation, the higher the Full GC frequency, but the shorter the Full GC time; on the contrary, the new generation setting The smaller it is, the larger the old generation is and the lower the frequency of Full GC, but the more time each Full GC consumes. The suggestions are as follows:
The values ??of -Xms and -Xmx are set to be equal. The heap size defaults to the size specified by -Xms. When the default free heap memory is less than 40%, the JVM will expand the heap to The size specified by -Xmx; when the free heap memory is greater than 70%, the JVM will reduce the heap to the size specified by -Xms. If the memory demand cannot be met after Full GC, it will be dynamically adjusted. This stage is relatively resource-consuming.
The new generation should be set as large as possible to allow objects to survive in the new generation for a longer period of time. Each Minor GC must collect as many garbage objects as possible to prevent or delay objects from entering the old generation. opportunity to reduce the frequency of Full GC occurring in your application.
If you use the CMS collector in the old generation, the new generation does not need to be too large, because the parallel collection speed of CMS is also very fast, and the concurrent marking and concurrent clearing phases of the collection process are time-consuming. Can be executed concurrently with user threads.
Setting the size of the method area. Before 1.6, you need to consider the constants, static variables, etc. that are dynamically added when the system is running. In 1.7, as long as it can almost accommodate the class information that is dynamically loaded at startup and later. That’s it.
In terms of code implementation, performance problems such as program waiting and memory leaks may not only have problems with JVM configuration, but also have a lot to do with code implementation:
Avoid creating overly large objects and arrays: Overly large objects or arrays will directly enter the old generation when the new generation does not have enough space to accommodate them. If they are short-lived large objects, Full GC will start in advance.
Avoid loading a large amount of data at the same time, such as fetching a large amount of data from the database at one time, or reading a large number of records from Excel at one time. You can read in batches and clear the references as soon as possible.
When there are references to objects in the collection, the references in the collection must be cleared as soon as possible after these objects are used. These useless objects must be recycled as soon as possible to avoid entering the old age.
Soft references and weak references can be used in appropriate scenarios (such as implementing caching). For example, soft references are used to allocate instances of ObjectA: SoftReference objectA=new SoftReference(); when memory is generated Before overflow, objectA will be included in the recycling range for secondary recycling. If there is not enough memory for this recycling, a memory overflow exception will be thrown.
Avoid an infinite loop. After an infinite loop occurs, a large number of instances may be repeatedly generated in the loop body, causing the memory space to be quickly filled up.Try to avoid waiting for long periods of time for external resources (database, network, equipment resources, etc.), shorten the life cycle of objects, and avoid entering the old age. If the results cannot be returned in time, you can use them appropriately. Asynchronous processing methods, etc.
(4) JVM problem troubleshooting record case
JVM service problem troubleshooting https://blog.csdn.net/jacin1/article/details/44837595
unforgettable troubleshooting of frequent Full GC process http://caogen81.iteye.com/blog/1513345
Frequent troubleshooting of online FullGC https://blog.csdn.net/wilsonpeng3 /article/details/70064336/
[JVM] Online application troubleshooting https://www.cnblogs.com/Dhouse/p/7839810.html
A troubleshooting of FullGC in JVM Process http://iamzhongyong.iteye.com/blog/1830265
Troubleshooting case of excessive CPU caused by JVM memory overflow https://blog.csdn.net/nielinqi520/article/details/78455614
A java memory leak troubleshooting case https://blog.csdn.net/aasgis6u/article/details/54928744
(5) Common JVM parameter reference:
Parameters | Description | Instance |
---|---|---|
-Xms | Initial heap size, 1/64 of default physical memory | -Xms512M |
-Xmx | Maximum heap size, default physical memory 1/4 | -Xms2G |
-Xmn | New generation memory size, the official recommendation is 3/8 | ## of the entire heap #-Xmn512M|
Thread stack size, jdk1.5 and later defaults to 1M, before the default is 256k | -Xss512k | |
Set the ratio between the new generation and the old generation. For example: if it is 3, it means that the ratio between the young generation and the old generation is 1:3, and the young generation accounts for 1/4 of the entire young generation and the old generation. | -XX:NewRatio=3 | |
The ratio of the Eden area to the two Survivor areas in the young generation. Note that there are two Survivor areas. For example: 8, means Eden: Survivor=8:1:1, one Survivor area accounts for 1/8 of the entire young generation | -XX:SurvivorRatio=8 | |
Initial value of the permanent generation, the default is 1/64 of the physical memory | -XX:PermSize=128M | |
Maximum permanent generation size, default is 1/4 of physical memory | -XX:MaxPermSize=256M | |
Print class loading information on the console | ||
Print garbage collection log on the console | ||
Print the GC log, the content is simple | ||
Print GC log with detailed content | ||
in the GC log Add timestamp | ||
Specify gc log path | -Xloggc:/data/jvm/gc .log | |
Young generation sets the serial collector Serial | ||
Young generation sets parallel collector Parallel Scavenge | ||
Set Parallel The number of CPUs used during Scavenge collection. Number of parallel collection threads. | -XX:ParallelGCThreads=4 | |
Set the maximum time for Parallel Scavenge recycling (milliseconds) | -XX:MaxGCPauseMillis=100 | |
Set Parallel Scavenge garbage collection time as a percentage of program running time. The formula is 1/(1 n) | -XX:GCTimeRatio=19 | |
Set the old generation to be collected by the parallel collector ParallelOld Collector | ||
Set the old generation concurrent collector CMS | ||
Set the CMS collector to incremental mode, suitable for single CPU situations. |
java tutorial column, welcome to learn!
The above is the detailed content of Why does jvm need performance tuning?. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

The settings.json file is located in the user-level or workspace-level path and is used to customize VSCode settings. 1. User-level path: Windows is C:\Users\\AppData\Roaming\Code\User\settings.json, macOS is /Users//Library/ApplicationSupport/Code/User/settings.json, Linux is /home//.config/Code/User/settings.json; 2. Workspace-level path: .vscode/settings in the project root directory

To correctly handle JDBC transactions, you must first turn off the automatic commit mode, then perform multiple operations, and finally commit or rollback according to the results; 1. Call conn.setAutoCommit(false) to start the transaction; 2. Execute multiple SQL operations, such as INSERT and UPDATE; 3. Call conn.commit() if all operations are successful, and call conn.rollback() if an exception occurs to ensure data consistency; at the same time, try-with-resources should be used to manage resources, properly handle exceptions and close connections to avoid connection leakage; in addition, it is recommended to use connection pools and set save points to achieve partial rollback, and keep transactions as short as possible to improve performance.

DependencyInjection(DI)isadesignpatternwhereobjectsreceivedependenciesexternally,promotingloosecouplingandeasiertestingthroughconstructor,setter,orfieldinjection.2.SpringFrameworkusesannotationslike@Component,@Service,and@AutowiredwithJava-basedconfi

Use classes in the java.time package to replace the old Date and Calendar classes; 2. Get the current date and time through LocalDate, LocalDateTime and LocalTime; 3. Create a specific date and time using the of() method; 4. Use the plus/minus method to immutably increase and decrease the time; 5. Use ZonedDateTime and ZoneId to process the time zone; 6. Format and parse date strings through DateTimeFormatter; 7. Use Instant to be compatible with the old date types when necessary; date processing in modern Java should give priority to using java.timeAPI, which provides clear, immutable and linear

TheJVMenablesJava’s"writeonce,runanywhere"capabilitybyexecutingbytecodethroughfourmaincomponents:1.TheClassLoaderSubsystemloads,links,andinitializes.classfilesusingbootstrap,extension,andapplicationclassloaders,ensuringsecureandlazyclassloa

ChromecanopenlocalfileslikeHTMLandPDFsbyusing"Openfile"ordraggingthemintothebrowser;ensuretheaddressstartswithfile:///;2.SecurityrestrictionsblockAJAX,localStorage,andcross-folderaccessonfile://;usealocalserverlikepython-mhttp.server8000tor

Pre-formanceTartuptimeMoryusage, Quarkusandmicronautleadduetocompile-Timeprocessingandgraalvsupport, Withquarkusoftenperforminglightbetterine ServerLess scenarios.2.Thyvelopecosyste,

Networkportsandfirewallsworktogethertoenablecommunicationwhileensuringsecurity.1.Networkportsarevirtualendpointsnumbered0–65535,withwell-knownportslike80(HTTP),443(HTTPS),22(SSH),and25(SMTP)identifyingspecificservices.2.PortsoperateoverTCP(reliable,c
