JVM parameters and memory model

1. Why should we optimize the jvm?

In the local development environment, we rarely encounter the need to optimize the jvm, but in the production environment, we may have the following requirements:

  • The running application is "stuck", the log does not output, and the program does not respond

  • The CPU load of the server suddenly increases

  • How to allocate the number of threads in multithreaded applications?

  • ...

Note: the jdk version used is 1.0 8 .

2. Operating parameters of jvm

There are many parameters that can be set in the jvm, so that the jvm can run efficiently in various environments. Most parameters can be left as default.

2.1. Three parameter types

The parameter types of jvm are divided into three categories:

  • Standard parameters

    • help
    • version
  • -X parameter (non-standard parameter)

    • Xint
    • Xcomp
  • -XX parameter (high utilization rate)

    • XX:newSize
    • XX:+UseSerialGC

2. Standard parameters

The standard parameters of the JVM are generally very stable and will not change in future JVM versions. You can use java - help to retrieve all the standard parameters.

[root@node01 ~]# java ‐help
 usage: java [‐options] class [args...]
					(Execution class)
or java [‐options] ‐jar jarfile [args...]
			(implement jar file)
Options include:
‐d 32       Using 32-bit data model (If available)
‐d 64       Using 64 bit data model (If available)
‐server choice "server" VM
				default VM yes server,
				Because you are running on a server computer.
‐cp <Catalogue and zip/jar Class search path for file>
‐classpath <Catalogue and zip/jar Class search path for file>
			use : Delimited directory, JAR archives
			and ZIP File list, Used to search for class files.
‐D<name>=<value>
			Set system properties
‐verbose:[class|gc|jni]
			Enable verbose output
‐version Output product version and exit
‐version:<value>
			warning: This feature is obsolete, Will be in
			Removed from future releases.
			The specified version is required to run
‐showversion Output product version and continue
‐jre‐restrict‐search | ‐no‐jre‐restrict‐search
			warning: This feature is obsolete, Will be in
			Removed from future releases.
			Include in version search/Exclude user specific JRE
‐? ‐help Output this help message
‐X Output help for nonstandard options
‐ea[:<packagename>...|:<classname>]
‐enableassertions[:<packagename>...|:<classname>]
			Enables assertions at the specified granularity
‐da[:<packagename>...|:<classname>]
‐disableassertions[:<packagename>...|:<classname>]
			Disables assertions with the specified granularity
-esa | ‐enablesystemassertions
			Start system assertion
‐dsa | ‐disablesystemassertions
			Disable system assertion
‐agentlib:<libname>[=<option>]
			Load native agent Library <libname>, for example ‐agentlib:hprof
			See also  ‐agentlib:jdwp=help and ‐agentlib:hprof=help
‐agentpath:<pathname>[=<option>]
			Load native agent library by full pathname
‐javaagent:<jarpath>[=<option>]
			load Java Programming language agent, see also java.lang.instrument
‐splash:<imagepath>
			Displays the startup screen using the specified image				

2. 2. 1. Actual combat

Actual combat 1: check the jvm version
[root@node01 ~]# java ‐version
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
#- the showversion parameter means that the version information is printed first and then the following commands are executed. It is very useful during debugging,
It will be used later.
Actual combat 2: set system attribute parameters through - D
public class TestJVM {
    
	public static void main(String[] args) {
		String str = System.getProperty("str");
		if (str == null) {
			System.out.println("zhangcc");
		} else {
			System.out.println(str);
		}
	}
}

Compile and test:

[root@node01 test]# javac TestJVM.java
#test
[root@node01 test]# java TestJVM
zhangcc
[root@node01 test]# java ‐Dstr=123 TestJVM
123

2. 2. 2. - server and - client parameters

You can set the running parameters of the jvm through - server or - client.

  • The difference between them is that the initial heap space of the Server VM will be larger. By default, the parallel garbage collector is used, which is slow to start and fast to run.

  • The Client VM will be relatively conservative and the initial heap space will be smaller. The serial garbage collector is used to make the JVM start faster, but the running speed will be slower than the Serverm mode.

  • When the JVM starts, it will automatically choose whether to use Server or Client type JVM according to the hardware and operating system.

  • 32-bit operating system

    • In the case of a Windows system, the Client type JVM is used by default regardless of the hardware configuration

    • If the machine is configured with more than 2 GB of memory and more than 2 CPU s on other operating systems, the server mode is used by default, otherwise the client mode is used.

  • 64 bit operating system

    • Only server type, not client type.

Test:

[root@node01 test]# java ‐client ‐showversion TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
zhangcc
[root@node01 test]# java ‐server ‐showversion TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
zhangcc
#Because the machine is a 64 bit system, the client mode is not supported

2.3, - X parameter

The - x parameter of the jvm is a non-standard parameter. The parameters may be different in different versions of the jvm. You can view the non-standard parameters through java -X.

[root@node 01  test]# java ‐X
    -Xmixed           Mixed mode execution (default)
    -Xint             Interpretation mode execution only
    -Xbootclasspath:<use ; Separate directories and zip/jar file>
                      Set the search path to guide classes and resources
    -Xbootclasspath/a:<use ; Separate directories and zip/jar file>
                      Append to the end of the boot classpath
    -Xbootclasspath/p:<use ; Separate directories and zip/jar file>
                      Before the boot classpath
    -Xdiag            Display additional diagnostic messages
    -Xnoclassgc       Disable class garbage collection
    -Xincgc           Enable incremental garbage collection
    -Xloggc:<file>    take GC The status is recorded in the file (Time stamped)
    -Xbatch           Disable background compilation
    -Xms<size>        Set initial Java Heap size
    -Xmx<size>        Set maximum Java Heap size
    -Xss<size>        set up Java Thread stack size
    -Xprof            output cpu Profile data
    -Xfuture          Enable the most stringent checks, Expected future defaults
    -Xrs              reduce Java/VM Use of operating system signals (Refer to the documentation)
    -Xcheck:jni       yes JNI Function to perform additional checks
    -Xshare:off       Do not attempt to use shared class data
    -Xshare:auto      Use shared class data where possible (default)
    -Xshare:on        Require shared data, Otherwise, it will fail.
    -XshowSettings    Show all settings and continue
    -XshowSettings:all
                      Show all settings and continue
    -XshowSettings:vm Show all and vm Relevant settings and continue
    -XshowSettings:properties
                      Show all property settings and continue
    -XshowSettings:locale
                      Show all locale related settings and continue

-X Options are nonstandard, If there is any change, Without notice.

2. 3. 1 ,-Xint,-Xcomp,-Xmixed

  • In interpreted mode, the - Xint flag forces the JVM to execute all bytecodes. Of course, this will slow down the running speed, usually 10 times or more.

  • Xcomp parameter is just the opposite (- Xint). When used for the first time, the JVM will compile all bytecodes into local code, resulting in maximum optimization.

    • However, many applications will also suffer some performance losses when using - xcomp. Of course, this is less than using - Xint, because - xcomp does not enable the JVM to enable all the functions of the JIT compiler. The JIT compiler can judge whether to compile or not. If all code is compiled, it is meaningless for some code that is executed only once.
  • Xmixed is a mixed mode, which mixes interpretation mode with compilation mode. It is up to the jvm to decide

The default mode of jvm is also the recommended mode.

Example: force set operation mode

# Force set to interpretation mode
[root@node 01  test]# java ‐showversion ‐Xint TestJVM
java version " 1. 8. 0 _ 141 "
Java(TM) SE Runtime Environment (build  1. 8. 0 _ 141 ‐b 15 )
Java HotSpot(TM)  64 ‐Bit Server VM (build  25. 141 ‐b 15 , interpreted mode)
    
zhangcc

#Force to compile mode
[root@node 01  test]# java ‐showversion ‐Xcomp TestJVM
java version " 1. 8. 0 _ 141 "
Java(TM) SE Runtime Environment (build  1. 8. 0 _ 141 ‐b 15 )
Java HotSpot(TM)  64 ‐Bit Server VM (build  25. 141 ‐b 15 , compiled mode)
    
zhangcc
#Note: in compilation mode, the first execution will be slower than that in interpretation mode. Pay attention to observation.
    
#Default blend mode
[root@node 01  test]# java ‐showversion TestJVM
java version " 1. 8. 0 _ 141 "
Java(TM) SE Runtime Environment (build  1. 8. 0 _ 141 ‐b 15 )
Java HotSpot(TM)  64 ‐Bit Server VM (build  25. 141 ‐b 15 , mixed mode)
zhangcc

2.4, - XX parameters

-XX parameter is also a non-standard parameter, which is mainly used for jvm tuning and debug ging.

-There are two ways to use XX parameter, one is boolean type and the other is non boolean type:

  • boolean type

    • Format: - XX: [±] < name > indicates that the < name > attribute is enabled or disabled
    • For example: - XX:+DisableExplicitGC means that manual calling GC operation is disabled, that is, calling system Invalid gc()
  • Non boolean type

    • Format: - XX: < name > = < value > indicates that the value of < name > attribute is < value >
    • For example: - XX:NewRatio= 1 indicates the ratio of the new generation to the old generation

Usage:

[root@node 01  test]# java ‐showversion ‐XX:+DisableExplicitGC TestJVM
java version " 1. 8. 0 _ 141 "
Java(TM) SE Runtime Environment (build  1. 8. 0 _ 141 ‐b 15 )
Java HotSpot(TM)  64 ‐Bit Server VM (build  25. 141 ‐b 15 , mixed mode)
zhangcc

2.5, - Xms and - Xmx parameters

-Xms and - Xmx are the initial size and maximum size of the heap memory of the jvm, respectively.

-Xmx 2048 m: equivalent to - XX:MaxHeapSize. Set the maximum heap memory of the JVM to 2048 M.

-Xms 512 m: equivalent to - XX:InitialHeapSize. Set the JVM's initial heap memory to 512 M.

Properly adjusting the memory size of the jvm can make full use of server resources and make the program run faster.

Example:

[root@node 01  test]# java ‐Xms 512 m ‐Xmx 2048 m TestJVM
zhangcc

2.6. View the operating parameters of the jvm

Sometimes we need to check the operating parameters of the jvm. There may be two situations for this requirement:

First, print out the running parameters when running the java command;
Second, check the parameters of the running java process;

2. 6. 1. Print parameters when running java command

When running the java command to print parameters, you need to add the - XX: + printflagfinal parameter.

[Global flags]
    uintx AdaptiveSizeDecrementScaleFactor          = 4                                   {product}
    uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
    uintx AdaptiveSizePausePolicy                   = 0                                   {product}
    uintx AdaptiveSizePolicyCollectionCostMargin    = 50                                  {product}
    uintx AdaptiveSizePolicyInitializingSteps       = 20                                  {product}
    uintx AdaptiveSizePolicyOutputInterval          = 0                                   {product}
    uintx AdaptiveSizePolicyWeight                  = 10                                  {product}
    uintx AdaptiveSizeThroughPutPolicy              = 0                                   {product}
    uintx AdaptiveTimeWeight                        = 25                                  {product}
     bool AdjustConcurrency                         = false                               {product}
     bool AggressiveOpts                            = false                               {product}
     intx AliasLevel                                = 3                                   {C2 product}
     bool AlignVector                               = false                               {C2 product}
     intx AllocateInstancePrefetchLines             = 1                                   {product}
     intx AllocatePrefetchDistance                  = 192                                 {product}
     intx AllocatePrefetchInstr                     = 3                                   {product}
     intx AllocatePrefetchLines                     = 4                                   {product}
     intx AllocatePrefetchStepSize                  = 64                                  {product}
     intx AllocatePrefetchStyle                     = 1                                   {product}
     bool AllowJNIEnvProxy                          = false                               {product}
     bool AllowNonVirtualCalls                      = false                               {product}
     bool AllowParallelDefineClass                  = false                               {product}
     bool AllowUserSignalHandlers                   = false                               {product}
     bool AlwaysActAsServerClassMachine             = false                               {product}
     bool AlwaysCompileLoopMethods                  = false                               {product}
     bool AlwaysLockClassLoader                     = false                               {product}
     bool AlwaysPreTouch                            = false                               {product}
     bool AlwaysRestoreFPU                          = false                               {product}
     bool AlwaysTenure                              = false                               {product}
     bool AssertOnSuspendWaitFailure                = false                               {product}
     bool AssumeMP                                  = false                               {product}
     intx AutoBoxCacheMax                           = 128                                 {C2 product}
    uintx AutoGCSelectPauseMillis                   = 5000                                {product}
     intx BCEATraceLevel                            = 0                                   {product}
     intx BackEdgeThreshold                         = 100000                              {pd product}
     bool BackgroundCompilation                     = true                                {pd product}
    uintx BaseFootPrintEstimate                     = 268435456                           {product}
     intx BiasedLockingBulkRebiasThreshold          = 20                                  {product}
     intx BiasedLockingBulkRevokeThreshold          = 40                                  {product}
     intx BiasedLockingDecayTime                    = 25000                               {product}
     intx BiasedLockingStartupDelay                 = 4000                                {product}
     bool BindGCTaskThreadsToCPUs                   = false                               {product}
     bool BlockLayoutByFrequency                    = true                                {C2 product}
     intx BlockLayoutMinDiamondPercentage           = 20                                  {C2 product}
     bool BlockLayoutRotateLoops                    = true                                {C2 product}
     bool BranchOnRegister                          = false                               {C2 product}
     bool BytecodeVerificationLocal                 = false                               {product}
..............................
uintx YoungGenerationSizeSupplement             = 80                                  {product}
uintx YoungGenerationSizeSupplementDecay        = 8                                   {product}
    uintx YoungPLABSize                             = 4096                                {product}
     bool ZeroTLAB                                  = false                               {product}
     intx hashCode                                  = 5                                   {product}
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.141-b12, mixed mode)

It can be seen from the above information that the parameters have boolean type and number type, and the value operator is = or: =, representing the default value and the modified value respectively.

Example:

java ‐XX:+PrintFlagsFinal ‐XX:+VerifySharedSpaces ‐version
intx ValueMapInitialSize =  11                 
{C 1  product}
intx ValueMapMaxLoopSize =  8                   
{C 1  product}
intx ValueSearchLimit =  1000               
{C 2  product}
bool VerifyMergedCPBytecodes = true
{product}
bool VerifySharedSpaces := true
{product}
intx WorkAroundNPTLTimedWaitHang =  1                   
{product}
uintx YoungGenerationSizeIncrement =  20                 
{product}
uintx YoungGenerationSizeSupplement =  80                 
{product}
uintx YoungGenerationSizeSupplementDecay =  8                   
{product}
uintx YoungPLABSize =  4096               
{product}
bool ZeroTLAB = false
{product}
intx hashCode =  5                   
{product}
java version " 1. 8. 0 _ 141 "
Java(TM) SE Runtime Environment (build  1. 8. 0 _ 141 ‐b 15 )
Java HotSpot(TM)  64 ‐Bit Server VM (build  25. 141 ‐b 15 , mixed mode)
    
#You can see that the parameter VerifySharedSpaces has been modified.   

2. 6. 2. View running jvm parameters

If you want to view the running jvm, you need to view it with the help of jinfo command.

First, observe the parameters of tomcat to start the next test on the virtual machine.

#View all parameters. Usage: jinfo ‐ flags < process ID >
#View java processes through jps or jps ‐ l
[root@node 01  bin]# jps
6346  Jps
6219  Bootstrap
    
[root@node 01  bin]# jps ‐l
6358  sun.tools.jps.Jps
6219  org.apache.catalina.startup.Bootstrap
    
[root@node 01  bin]# jinfo ‐flags  
Attaching to process ID  6219 , please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is  25. 141 ‐b 15
Non‐default VM flags: ‐XX:CICompilerCount= 2  ‐XX:InitialHeapSize= 31457280 
‐XX:MaxHeapSize= 488636416  ‐XX:MaxNewSize= 162529280  ‐
XX:MinHeapDeltaBytes= 524288  ‐XX:NewSize= 10485760  ‐XX:OldSize= 20971520  ‐
XX:+UseCompressedClassPointers ‐XX:+UseCompressedOops ‐
XX:+UseFastUnorderedTimeStamps ‐XX:+UseParallelGC
Command line: ‐Djava.util.logging.config.file=/tmp/apache‐tomcat‐
7. 0. 57 /conf/logging.properties ‐
Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager ‐
Djava.endorsed.dirs=/tmp/apache‐tomcat‐ 7. 0. 57 /endorsed ‐
Dcatalina.base=/tmp/apache‐tomcat‐ 7. 0. 57  ‐Dcatalina.home=/tmp/apache‐
tomcat‐ 7. 0. 57  ‐Djava.io.tmpdir=/tmp/apache‐tomcat‐ 7. 0. 57 /temp
    
#View the value of a parameter. Usage: jinfo ‐ flag < parameter name > < process ID >
[root@node 01  bin]# jinfo ‐flag MaxHeapSize  
‐XX:MaxHeapSize= 488636416

3. Memory model of jvm

The memory model of jvm is quite different between 1.7 and 1.8. Although this course takes 1.8 as an example, we also need to understand the memory model of 1.7, so in the next, we will learn the memory model of 1.7 first and then 1.8.

3. 1 ,jdk 1. 7 heap memory model

  • Young youth district (generation)

    The Young area is divided into three parts: Eden area and two Survivor areas with the same size. In the Survivor area, only one of them is used at a certain time, and the other is reserved for copying objects during garbage collection. When the Eden area becomes full, the GC will move the surviving objects to the idle Survivor area. According to the strategy of the JVM, After several garbage collections, objects that still survive will be moved to the Tenured section.

  • Tenured elderly area
    The Tenured area mainly stores objects with a long life cycle, generally old objects. When some objects are copied and transferred in Young for a certain number of times, the objects will be transferred to the Tenured area. Generally, if the application level cache is used in the system, the objects in the cache will often be transferred to this area.

  • Perm permanent area
    The perm generation mainly saves class, method and filed objects. Generally, this part of the space will not overflow unless many classes are loaded at one time. However, when it comes to hot deployed application servers, sometimes Java Lang. outofmemoryerror: the error of permgen space may be caused by redeployment every time, but the class of the class is not uninstalled after redeployment, resulting in a large number of class objects saved in perm. In this case, restarting the application server can solve the problem.

  • Virtual zone:
    The difference between the maximum memory and the initial memory is the Virtual area.

3. 2 ,jdk 1. 8 heap memory model

As can be seen from the above figure, the memory model of jdk 1.8 consists of two parts, young generation + old generation.

Younger generation: Eden + 2 *Survivor

Old generation: OldGen

In JDK 1 The Perm area with the largest change in 8 is replaced with Metaspace.

It should be noted that the memory space occupied by Metaspace is not in the virtual machine, but in the local memory space, which is also the same as 1 The biggest difference between the permanent generation of 7.

3. Why should it be abandoned 1 Permanent area in 7?

The official website explains: http://openjdk.java.net/jeps/ one hundred and twenty-two

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.
 
Removing the permanent generation is for fusion HotSpot JVM And JRockit VM And make efforts because JRockit There is no permanent generation,
Permanent generation does not need to be configured.

In real use, because the permanent generation memory is often insufficient or memory leakage occurs, an exception is reported lang.OutOfMemoryError: PermGen. Based on this, the permanent area is discarded, and the meta space is used instead, and the local memory space is used instead.

3. 4. Check the heap memory usage through jstat command

The jstat command can view the usage of various parts of heap memory and the number of loaded classes. The format of the command is as follows:
jstat [- command options] [vmid] [interval / MS] [query times]

3. 4. 1. View class loading statistics

[root@node 01  ~]# jps
7080  Jps
6219  Bootstrap
    
[root@node 01  ~]# jstat ‐class  
Loaded Bytes Unloaded Bytes Time
  3273  7122. 3        0     0. 0       3. 98

explain:

  • Loaded: the number of class es loaded

  • Bytes: occupied space

  • Unloaded: unloaded quantity

  • Bytes: occupied space not loaded

  • Time: time

3. 4. 2. View compilation statistics

[root@node 01  ~]# jstat ‐compiler  
Compiled Failed Invalid Time FailedType FailedMethod
    2376      1       0     8. 04          1 
org/apache/tomcat/util/IntrospectionUtils setProperty

explain:

  • Compiled: compiled quantity.

  • Failed: number of failures

  • Invalid: unavailable quantity

  • Time: time

  • FailedType: failure type

  • FailedMethod: failed method

3. 4. 3. Garbage collection statistics

[root@node 01  ~]# jstat ‐gc  
S 0 C S 1 C S 0 U S 1 U EC EU OC OU MC
MU CCSC CCSU YGC YGCT FGC FGCT GCT
9216. 0 8704. 0  0. 0   6127. 3 62976. 0   3560. 4   33792. 0    20434. 9   
23808. 0 23196. 1 2560. 0 2361. 6      7    1. 078   1      0. 244    1. 323
    
#You can also specify the interval and times of printing, printing once every 1 second, a total of 5 times
[root@node 01  ~]# jstat ‐gc  621 9 10 00 
S 0 C S 1 C S 0 U S 1 U EC EU OC OU MC
MU CCSC CCSU YGC YGCT FGC FGCT GCT
9216. 0 8704. 0  0. 0   6127. 3 62976. 0   3917. 3   33792. 0    20434. 9   
23808. 0 23196. 1 2560. 0 2361. 6      7    1. 078   1      0. 244    1. 323
9216. 0 8704. 0  0. 0   6127. 3 62976. 0   3917. 3   33792. 0    20434. 9   
23808. 0 23196. 1 2560. 0 2361. 6      7    1. 078   1      0. 244    1. 323
9216. 0 8704. 0  0. 0   6127. 3 62976. 0   3917. 3   33792. 0    20434. 9   
23808. 0 23196. 1 2560. 0 2361. 6      7    1. 078   1      0. 244    1. 323
9216. 0 8704. 0  0. 0   6127. 3 62976. 0   3917. 3   33792. 0    20434. 9   
23808. 0 23196. 1 2560. 0 2361. 6      7    1. 078   1      0. 244    1. 323
9216. 0 8704. 0  0. 0   6127. 3 62976. 0   3917. 3   33792. 0    20434. 9   
23808. 0 23196. 1 2560. 0 2361. 6      7    1. 078   1      0. 244    1. 323

explain:

  • S 0 C: the size of the first Survivor area (KB)

  • S 1 C: the size of the second Survivor area (KB)

  • S 0 U: use size of the first Survivor area (KB)

  • S 1 U: usage size of the second Survivor area (KB)

  • EC: Eden zone size (KB)

  • EU: used size of Eden area (KB)

  • OC: Old area size (KB)

  • OU: Old usage size (KB)

  • MC: method area size (KB)

  • MU: method area usage size (KB)

  • CCSC: compressed class space size (KB)

  • CCU: compressed class space usage size (KB)

  • YGC: garbage collection times of young generation

  • YGCT: waste collection time of young generation

  • FGC: garbage collection times in old age

  • FGCT: waste collection time in old age

  • GCT: total time consumed by garbage collection

4. jmap usage and memory overflow analysis

jstat can be used to statistically analyze the memory of jvm heap, while jmap can obtain more detailed contents, such as summary of memory usage, location and analysis of memory overflow.

4. 1. Check the memory usage

[root@node^01 ~]# jmap ‐heap 6219
Attaching to process ID  6219 , please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is  25. 141 ‐b 15

using thread‐local object allocation.
Parallel GC with  2  thread(s)
    
Heap Configuration: #Heap memory configuration information
	MinHeapFreeRatio =  0
	MaxHeapFreeRatio =  100
	MaxHeapSize =  488636416  ( 466. 0 MB)
	NewSize =  10485760  ( 10. 0 MB)
	MaxNewSize =  162529280  ( 155. 0 MB)
	OldSize =  20971520  ( 20. 0 MB)
	NewRatio =  2
	SurvivorRatio =  8
	MetaspaceSize =  21807104  ( 20. 796875 MB)
	CompressedClassSpaceSize =  1073741824  ( 1024. 0 MB)
	MaxMetaspaceSize =  17592186044415  MB
	G 1 HeapRegionSize =  0  ( 0. 0 MB)
    
Heap Usage: # Heap memory usage
	PS Young Generation #Young generation
	Eden Space:
	capacity =  123731968  ( 118. 0 MB)
	used =  1384736  ( 1. 320587158203125 MB)
	free =  122347232  ( 116. 67941284179688 MB)
  	 1. 1191416594941737 % used
From Space:
	capacity =  9437184  ( 9. 0 MB)
	used =  0  ( 0. 0 MB)
	free =  9437184  ( 9. 0 MB)
   	0. 0 % used
To Space:
	capacity =  9437184  ( 9. 0 MB)
	used =  0  ( 0. 0 MB)
	free =  9437184  ( 9. 0 MB)
   	0. 0 % used
PS Old Generation #Tenured 
	capacity =  28311552  ( 27. 0 MB)
	used =  13698672  ( 13. 064071655273438 MB)
	free =  14612880  ( 13. 935928344726562 MB)
   	48. 38545057508681 % used
	13648  interned Strings occupying  1866368  bytes.        

4.2. Check the number and size of objects in memory

#View all objects, both active and inactive
jmap ‐histo <pid> | more
    
#View active objects
jmap ‐histo:live <pid> | more
 
[root@node 01  ~]# jmap ‐histo:live  6219  | more
  
  num #instances #bytes class name
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
   1 :          37437        7914608   [C
   2 :          34916         837984   java.lang.String
   3 :            884         654848   [B
   4 :          17188         550016   java.util.HashMap$Node
   5 :           3674         424968   java.lang.Class
   6 :           6322         395512   [Ljava.lang.Object;
   7 :           3738         328944   java.lang.reflect.Method
   8 :           1028         208048   [Ljava.util.HashMap$Node;
   9 :           2247         144264   [I
  10 :           4305         137760  
java.util.concurrent.ConcurrentHashMap$Node
  11 :           1270         109080   [Ljava.lang.String;
  12 :             64          84128  
[Ljava.util.concurrent.ConcurrentHashMap$Node;
  13 :           1714          82272   java.util.HashMap
  14 :           3285          70072   [Ljava.lang.Class;
  15 :           2888          69312   java.util.ArrayList
  16 :           3983          63728   java.lang.Object
  17 :           1271          61008  
org.apache.tomcat.util.digester.CallMethodRule
  18 :           1518          60720   java.util.LinkedHashMap$Entry
  19 :           1671          53472  
com.sun.org.apache.xerces.internal.xni.QName
  20 :             88          50880   [Ljava.util.WeakHashMap$Entry;
  21 :            618          49440   java.lang.reflect.Constructor
  22 :           1545          49440   java.util.Hashtable$Entry
  23 :           1027          41080   java.util.TreeMap$Entry
  24 :            846          40608  
	..............ellipsis........
#Object description
B byte
C char
D double
F float
I int
J long
Z boolean
[ Array, such as[I express int[]
[L+Class name other objects                                        

4. 3. dump the memory usage into the file

Sometimes we need to dump the current memory of the jvm into a file, and then analyze it. jmap also supports dump into a file.

#Usage:
    jmap ‐dump:format=b,file=dumpFileName <pid>
        
#Examples
    jmap ‐dump:format=b,file=/tmp/dump.dat  6219    

You can see that dump has been generated under / tmp Dat file.

4. Analyze dump file through jhat

In the previous section, we dump the memory of the jvm into a file. This file is a binary file, which is inconvenient to view. At this time, we can view it with the help of jhat tool.

#Usage:
    jhat ‐port <port> <file>
#Example:
[root@node 01  tmp]# jhat ‐port  9999  /tmp/dump.dat
Reading from /tmp/dump.dat...
Dump file created Mon Sep  10 01 : 04 : 21  CST  2018
Snapshot read, resolving...
Resolving  204094  objects...
Chasing references, expect  40 
dots........................................
Eliminating duplicate references........................................
Snapshot resolved.
Started HTTP server on port  9999
Server is ready.   

Open a browser to access: http: / / 192 168. 40. 133 : 9999 /


OQL query function is at the end.

4.5. Analyze dump file through MAT tool

4. 5. 1. Introduction to MAT tool

MAT(Memory Analyzer Tool), a memory analysis tool based on Eclipse, is a fast and feature rich JAVA heap analysis tool, which can help us find memory leaks and reduce memory consumption. Use the memory analysis tool to analyze from a large number of objects, quickly calculate the occupation size of objects in memory, see who prevented the garbage collector from recycling, and visually view the objects that may cause this result through the report.

Official website address: https://www.eclipse.org/mat/

4. 5. 2. Download and install

Download address: https://www.eclipse.org/mat/downloads.php

Will download the obtained memoryanalyzer-1.8.0.20180604-win32 win32. x86_ Unzip 64.zip:

4. 5. 3. Use




To view an object and its dependencies:

To view an analysis of possible memory leaks:

5. Actual combat: location and analysis of memory overflow

Memory overflow is often encountered in the actual production environment. For example, constantly writing data to a collection, dead circulation, reading oversized files and so on may cause memory overflow.

If there is a memory overflow, first of all, we need to locate the link where the memory overflow occurs and analyze whether it is normal or abnormal. If it is a normal demand, we should consider increasing the memory setting. If it is an abnormal demand, we should modify the code and fix the bug.

First, we have to learn how to locate the problem before we analyze it. How to locate the problem? We need to use jmap and MAT tools for location analysis.

Next, we simulate the memory overflow scenario.

5.1. Simulate memory overflow

Write code to add 1 million strings to the List set, each consisting of 1000 UUID s. If the program can execute normally, print ok at last.

package cn.zhangcc.jvm;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class TestJvmOutOfMemory {
    public static void main(String[] args) {
		List<Object> list = new ArrayList<>();
			for (int i =  0 ; i <  10000000 ; i++) {
				String str = "";
				for (int j =  0 ; j <  1000 ; j++) {
					str += UUID.randomUUID().toString();
				}
				list.add(str);
			}
			System.out.println("ok");
	}
}
#The parameters are as follows:
-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

5.2. Operation test

The test results are as follows:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid 5348 .hprof ...
Heap dump file created [ 8137186  bytes in  0. 032  secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java: 3332 )
at
java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuil
der.java: 124 )
at
java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java: 448 )
at java.lang.StringBuilder.append(StringBuilder.java: 136 )
at cn.itcast.jvm.TestJvmOutOfMemory.main(TestJvmOutOfMemory.java: 14 )
    
Process finished with exit code  1

You can see that when a memory overflow occurs, the dump file will be to java_pid 5348 .hprof.

5.3. Import into MAT tool for analysis

It can be seen that 91.03% of the memory is occupied by the Object [] array, so it is suspicious.

Analysis: this suspicion is correct, because it has occupied more than 90% of the memory, which is very likely to have memory overflow.

View Details:

You can see that a large number of uuid strings are stored in the collection.

6. Use of jstack

Sometimes we need to check the thread execution in the jvm. For example, we find that the CPU load of the server suddenly increases, deadlocks and loops occur. How can we analyze them?

Since the program runs normally without any output, and there is no problem in the log, you need to look at the execution of the internal thread of the jvm, and then analyze it to find out the reason.

At this time, you need to use the jstack command. The function of jstack is to take a snapshot of the threads of the running jvm and print it:

#Usage: jstack < PID >
    
[root@node 01  bin]# jstack  2203
Full thread dump Java HotSpot(TM)  64 ‐Bit Server VM ( 25. 141 ‐b 15  mixed mode): 

"Attach Listener" # 24  daemon prio= 9  os_prio= 0  tid= 0 x 00007 fabb 4001000 
nid= 0 x 906  waiting on condition [ 0 x 0000000000000000 ]
java.lang.Thread.State: RUNNABLE
    
 "http‐bio‐ 8080 ‐exec‐ 5 " # 23  daemon prio= 5  os_prio= 0  tid= 0 x 00007 fabb 057 c 000 
nid= 0 x 8 e 1  waiting on condition [ 0 x 00007 fabd 05 b 8000 ]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
‐ parking to wait for < 0 x 00000000 f 8508360 > (a
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java: 175 )
at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awa
it(AbstractQueuedSynchronizer.java: 2039 )
at
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java: 44
2 )
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java: 104 )
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java: 32 )
at
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java: 1074 )
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java: 1134 )
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java: 624 )
at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java: 61 )
at java.lang.Thread.run(Thread.java: 748 )
    
"http‐bio‐ 8080 ‐exec‐ 5 " # 23  daemon prio= 5  os_prio= 0  tid= 0 x 00007 fabb 057 c 000 
nid= 0 x 8 e 1  waiting on condition [ 0 x 00007 fabd 05 b 8000 ]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
‐ parking to wait for < 0 x 00000000 f 8508360 > (a
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java: 175 )
at
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awa
it(AbstractQueuedSynchronizer.java: 2039 )
at
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java: 442 )
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java: 104 )
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java: 32 )
at
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java: 1074 )
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java: 1134 )
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java: 624 )
at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java: 61 )
at java.lang.Thread.run(Thread.java: 748 )
..........slightly........................

6.1. Thread status

In Java, thread states are divided into six types:

  • Initial state (NEW)

    • When a Thread object is created, but start() has not been called to start the Thread, the Thread is in the initial state.
  • RUNNABLE: in Java, RUNNABLE includes ready state and running state.

    • Ready

      • The thread in this state has obtained all the resources required for execution, and can run as long as the CPU allocates execution rights.

      • All ready threads are stored in the ready queue.

    • Running state

      • Get the CPU execution right and the thread being executed.
      • Since a CPU can only execute one thread at a time, each CPU has only one running thread at each time.
  • BLOCKED

    • When an executing thread fails to request a resource, it will enter the blocking state.

    • In Java, blocking state refers to the state entered when the request for lock fails.

    • A blocking queue stores all threads in blocking state.

    • The thread in the blocking state will constantly request resources. Once the request is successful, it will enter the ready queue and wait for execution.

  • WAITING

    • When the wait, join and park functions are invoked in the current thread, the current thread will enter the wait state.

    • There is also a waiting queue to store all waiting threads.

    • A thread in a waiting state indicates that it needs to wait for instructions from other threads to continue running.

    • Threads entering the waiting state will release CPU execution rights and resources (such as locks)

  • TIMED_WAITING

    • When the running thread calls sleep(time), wait, join, parkNanos and parkUntil, it will enter this state;

    • Like the waiting state, it is not because the resource cannot be requested, but actively enters, and needs other threads to wake up after entering;

    • After entering this state, release the CPU Execution Authority ^ and the resources occupied by ^.

    • The difference from the waiting state: after the timeout, it automatically enters the blocking queue and starts competing for locks.

  • TERMINATED

    • The state of a thread after its execution ends.

6.2. Actual combat: deadlock problem

If a deadlock occurs in the production environment, we will see that the deployed program has no response. At this time, we can analyze it with the help of jstack. Let's find the cause of the deadlock in actual combat.

6. 2. 1. Construct deadlock

Write code and start two threads. Thread 1 gets the obj 1 lock. When it is ready to get the obj 2 lock, obj 2 has been locked by Thread 2, so a deadlock is sent.

public class TestDeadLock {
    
    private static Object obj 1  = new Object();
    
    private static Object obj 2  = new Object();
    
    public static void main(String[] args) {
		new Thread(new Thread 1 ()).start();
		new Thread(new Thread 2 ()).start();
	}
    
    private static class Thread1  implements Runnable{
		@Override
		public void run() {
			synchronized (obj 1 ){
				System.out.println("Thread 1  Got it obj 1  My lock!");
    			try {
                    // The meaning of pausing for 2 seconds is to let the Thread 2 thread get the lock of obj 2
                    Thread.sleep( 2000 );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            synchronized (obj 2 ){
				System.out.println("Thread 1  Got it obj 2  My lock!");
			}
		}
	}
    private static class Thread 2  implements Runnable{
		@Override
		public void run() {
			synchronized (obj2 ){
				System.out.println("Thread 2  Got it obj 2  My lock!");    
        	try {
                // The meaning of pausing for 2 seconds is to let Thread 1 get the lock of obj 1
             	Thread.sleep( 2000 );
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
           synchronized (obj 1 ){
				System.out.println("Thread 2  Got it obj 1  My lock!");
			}
		}
	}
}     

6. 2. 2. Running on linux

[root@node 01  test]# javac TestDeadLock.java
[root@node 01  test]# ll
 Total consumption 28
‐rw‐r‐‐r‐‐.  1  root root   184 9 November 10 : 39  TestDeadLock$ 1 .class
‐rw‐r‐‐r‐‐.  1  root root   843 9 November 10 : 39  TestDeadLock.class
‐rw‐r‐‐r‐‐.  1  root root  1567 9 November 10 : 39  TestDeadLock.java
‐rw‐r‐‐r‐‐.  1  root root  1078 9 November 10 : 39  TestDeadLock$Thread 1 .class
‐rw‐r‐‐r‐‐.  1  root root  1078 9 November 10 : 39  TestDeadLock$Thread 2 .class
‐rw‐r‐‐r‐‐.  1  root root   573 9 month    9 10 : 21  TestJVM.class
‐rw‐r‐‐r‐‐.  1  root root   261 9 month    9 10 : 21  TestJVM.java

[root@node 01  test]# java TestDeadLock
Thread 1  Got it obj 1  My lock!
Thread 2  Got it obj 2  My lock!
#There is a deadlock and the program will wait    

6. 2. 3. Analysis using jstack

[root@node 01  ~]# jstack  3256
Full thread dump Java HotSpot(TM)  64 ‐Bit Server VM ( 25. 141 ‐b 15  mixed mode):

................slightly..................
"Thread‐1":
	at TestDeadLock$Thread2.run(TestDeadLock.java:47)
	‐ waiting to lock <0x00000000f655dc40> (a java.lang.Object)
	‐ locked <0x00000000f655dc50> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)
"Thread‐0":
	at TestDeadLock$Thread1.run(TestDeadLock.java:27)
	‐ waiting to lock <0x00000000f655dc50> (a java.lang.Object)
	‐ locked <0x00000000f655dc40> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)
................slightly..................
Found 1 deadlock.  

In the output information, it has been seen that one deadlock is found, which can be clearly seen:

Thread 2 acquired the lock of < 0x00000000f655dc50 >, waiting for the lock of < 0 x 00000000f655dc40 >

Thread 1 has acquired the lock of < 0x00000000f655dc40 >, waiting to acquire the lock of < 0x00000000f655dc50 >

It can be seen that a deadlock has occurred.

7. Use of VisualVM tools

VisualVM can monitor the thread and memory, view the CPU time of the method and the objects in memory, the objects that have been GC, and reverse the allocated stack (for example, which objects allocate 100 String objects).
VisualVM is easy to use, almost 0 configured, and has rich functions, almost including all the functions of other JDK commands.

  • Memory information

  • Thread information

  • Dump heap (local process)

  • Dump thread (local process)

  • Open heap Dump. Heap Dump can be generated by jmap.

  • Open thread Dump

  • Generate application snapshot (including memory information, thread information, etc.)

  • Performance analysis. CPU analysis (calling time of each method, checking which methods take more time), memory analysis (memory occupied by various objects, checking which classes occupy more memory)

  • ...

7.1. Startup

Under the bin directory of the jdk installation directory, find jvisualvm Exe, double click to open it.

7.2. View local processes

7.3. View CPU, memory, class and thread operation information

7.4. View Thread details

You can also click the Dump button in the upper right corner to export the thread information, which is actually the executed jstack command.

7.5 sampler

The sampler can sample the CPU and memory for analysis within a period of time.

7.6. Monitor the remote jvm

Visual jvm can monitor not only local jvm processes, but also remote jvm processes. It needs to be implemented with the help of JMX technology.

7. 6. 1. What is JMX?

MX (Java Management Extensions) is a framework for implanting management functions for applications, devices, systems, etc. JMX can span a series of heterogeneous operating system platforms, system architectures and network transmission protocols, and flexibly develop seamless integrated system, network and service management applications.

7. 6. 2. Monitoring remote tomcat

To monitor the remote tomcat, you need to configure JMX in the remote Tomcat as follows:

#In the bin directory of tomcat, modify Catalina SH, add the following parameters

JAVA_OPTS="‐Dcom.sun.management.jmxremote ‐
Dcom.sun.management.jmxremote.port= 9999  ‐
Dcom.sun.management.jmxremote.authenticate=false ‐
Dcom.sun.management.jmxremote.ssl=false"
    
#These parameters mean:
#‐Dcom.sun.management.jmxremote: allows remote management using JMX
#‐Dcom.sun.management.jmxremote.port= 9999: JMX remote connection port
#‐Dcom.sun.management.jmxremote.authenticate=false: any user can connect without identity authentication
#‐Dcom.sun.management.jmxremote.ssl=false: do not use ssl

Save, exit and restart tomcat.

7. 6. 2. Monitoring remote tomcat

Add remote host:

Connection succeeded. The usage method is the same as before. You can monitor the remote tomcat process the same as monitoring the local jvm process.

Keywords: Java jvm jar

Added by DarkHavn on Wed, 23 Feb 2022 13:03:37 +0200