Java Performance Optimization Series 3.1[JVM tuning]

Source: Internet
Author: User
Tags xms

Java virtual machine memory model


The JVM virtual machine divides its memory data into program counters, virtual machine stacks, local method stacks, Java heaps, and method areas.

The program counter is used to store the next running instruction, and the virtual machine stack and the local method stack are used to hold the function call stack information, the Java heap is used to hold the data such as the objects required by the Java program to run, and the method area is used to store the program's class metadata information.

1. Procedure counter-Program Counter Register

is a small piece of memory space. Because Java is a thread-supported language, when the number of threads exceeds the number of CPUs, threads of the thread are polled to rob CPU resources based on time slices. For a single-core CPU, only one thread can run at a time, and other threads must be switched out. To do this, each thread must use a separate program counter that records the next instruction to be run. The counters between the threads do not affect each other and work independently; it is a thread-private memory space.

If the current thread is executing a Java method, the program counter records the Java bytecode address being executed, and if the current thread is executing a native method, the program counter is empty.


2. Java Virtual Machine stack

The Java Virtual machine stack is also a thread-private memory space that is created at the same time as the Java thread, which holds local variables, partial results, and participates in method invocation and return.

The Java Virtual Machine specification allows the size of the Java stack to be dynamic or fixed. In the Java Virtual Machine specification, two exceptions are defined in relation to the stack space: Stackoverflowerror and OutOfMemoryError.

If the thread is in the process of calculation, the requested stack depth is greater than the maximum available stack depth, the stackoverflowerror is thrown;

If the Java stack can be dynamically extended, and in the process of the expansion stack, there is not enough memory space to support the expansion of the stack, then throw outofmemoryerror.

In a hotspot virtual machine, you can use the-XSS parameter to set the size of the stack.

Look at the code:

Teststack.java

Package Com.oscar999.performance.jvmtune;import Org.junit.test;public class Teststack {private int count = 0;public void Recursion () {count ++;recursion ();} @Testpublic void Teststatck () {try{recursion ();} catch (Throwable e) {System.out.println ("Deep of the Stack is" +count); E.printstacktrace ();}}

Run results


If you adjust the size of the stack space, in Eclipse, set the following


Operation Result:


The depth has increased a lot.

The virtual machine stack saves contextual data at run time using a data structure called a stack frame. In the stack frame, the local variable table, the operand stack, the dynamic connection method and the return address of the method are stored.

Each method call is accompanied by the stack frame of the stack operation, corresponding to the return of the method represents the stack frame of the stack operation. If the method is called, the parameters and local variables of the method are relatively large, then the local variables in the stack frame are larger, the stack frame expands to satisfy the information required by the method call, so the size of the stack space required for a single method call is also more.

The result of the stack frame is as follows:


Use the Jclasslib tool to view the capacity of the maximum local variable table allocated by each method in the class file.

Can be downloaded in the Http://sourceforge.net/projects/jclasslib/files/jclasslib

You can use Jclasslib to see the words that are required for class files of the following classes

Package Com.oscar999.performance.jvmtune;public class Testwordreuse {public void Test1 () {{Long a = 0;} Long b = 0;} public void Test2 () {Long A = 0;long b = 0;}}

The result is 3, and one is 5.

Based on this, take a look at the system GC Recovery example:

Package Com.oscar999.performance.jvmtune;public class SYSTEMGC {/** * GC cannot reclaim B because B is also */public static void Test1 () in the local variable { {byte[] b = new BYTE[6 * 1024 * 1024];} System.GC (); System.out.println ("First explict GC Over");} /** * GC cannot be reclaimed because assigning null will destroy data in the local variable table */public static void Test2 () {{byte[] b = new Byte[6 * 1024x768 * 1024];b=null;} System.GC (); System.out.println ("First explict GC Over");} /** * GC can be recycled because variable a re-uses the word of variable B, GC root cannot find B */public static void Test3 () {{byte[] b = new BYTE[6 * 1024 * 1024];} int a=0; System.GC (); System.out.println ("First explict GC Over");} /** * GC is not recyclable because variable a uses the word of variable C again, B still exists */public static void Test4 () {{int c = 0;byte[] b = new BYTE[6 * 1024 * 1024];} int a=0; System.GC (); System.out.println ("First explict GC Over");} /** * GC can be recycled because variable a re-uses the word of variable c, variable D uses the character of variable b */public static void Test5 () {{int c = 0;byte[] b = new BYTE[6 * 1024 * 1024] ;} int A=0;int d=0; System.GC (); System.out.println ("First explict GC Over");} /** * * Can always reclaim B because the stack frame of the upper function has been destroyed */public static void main(String args[]) {test1 (); System.GC (); System.out.println ("second explict GC Over");}}


3. Local Method Stack

The local method stack is similar to the Java Virtual machine stack, where the Java Virtual machine stack is used to manage calls to Java functions, while the local method stack manages calls to local methods. Local methods are not implemented in Java, but are implemented in C. In Sun's hot spot virtual machine, the local method stack and the virtual machine stack are not distinguished. So, like a virtual machine stack, it throws Stackoverflowerror and OutOfMemoryError.


4. Java Heap

The most important part of the Java Runtime memory is that almost all objects and arrays are allocated space in the heap. The Java heap is divided into two parts of the new generation and the old age. The new generation is used to store objects that have just been produced and young objects, and if the object has not been recycled, long enough to survive, older objects will be moved into older generations.

The Cenozoic is divided into: Eden (Eden), Survivor Space0 (from space), Survivor Space1 (to space)


Take a look at the execution of the following code:

Package Com.oscar999.performance.jvmtune;public class TESTHEAPGC {/** * @param args */public static void main (string[] Arg s) {//TODO auto-generated method stubbyte[] B1 = new byte[1024*1204/2];byte[] B2 = new BYTE[1024*1204*8];B2 = NULL;B2 = n EW Byte[1204*1204*8];//system.gc ();}}
To run using the command line:

java-xx:+printgcdetails-xx:survivorratio=8-xx:maxtenuringthreshold=15-xms40m-xmx40m-xmn20m Com.oscar999.performance.JVMTune.TestHeapGC

Run results


Open up Mark's System.GC and run it again.


As you can see, after the full GC, the Cenozoic space is emptied and the objects that are not reclaimed are all moved into the Laosheng generation.


5. Method area
Similar to heap space, it is also shared by all threads in the JVM. method to go to the main saved information is the metadata of the class.

The type information, Chang, Domain information, method information of the class are important in the method area.

In hot Spot virtual machines, the method area is also known as the Permanent Zone, which is a separate memory space from the Java heap. Although it is called a permanent zone, the objects in the permanent zone can also be recycled by GC.

The recovery of GC in a permanent area is usually analyzed in two ways: 1. GC Recovery of a permanent zone constant pool 2. The permanent zone recycles the class metadata.

Look at the following code:

Package Com.oscar999.performance.jvmtune;public class TESTPERMGENGC {public void PERMGENGC () {for (int i=0;i< integer.max_value;i++) {String t = string.valueof (i). Intern ();}} public static void Main (string[] args) {TESTPERMGENGC test = new TESTPERMGENGC (); TEST.PERMGENGC ();}}

Run using the following command line:

Java-xx:permsize=2m-xx:maxpermsize=4m-xx:+printgcdetails Com.oscar999.performance.JVMTune.TestPermGenGC

Will find that the following logs have been printed:


That is, when the constant pool is saturated, the full GC always recovers the constant pool data smoothly, ensuring that the program continues to run stably.

Take a look at the recycling of class metadata,

To generate an instance of the class dynamically, use the Javassist

Can be downloaded to the following address:

Http://www.java2s.com/Code/Jar/j/Downloadjavassistjar.htm

Javabeanobject.java

Package Com.oscar999.performance.jvmtune;public class Javabeanobject {private String name = "java";p ublic string GetName () {return name;} public void SetName (String name) {this.name = name;}}

Testoneclassload.java

Package Com.oscar999.performance.jvmtune;import javassist. Cannotcompileexception;import javassist. Classpool;import javassist. Ctclass;import javassist. Notfoundexception;public class Testoneclassload {public void Testoneclassload () throws Cannotcompileexception,  Notfoundexception, Instantiationexception, illegalaccessexception {for (int i = 0; i < Integer.max_value; i++) {CtClass c = Classpool.getdefault (). Makeclass ("Geym" +i); C.setsuperclass (Classpool.getdefault (). Get (" Com.oscar999.performance.JVMTune.JavaBeanObject ")); Class CLZ = C.toclass (); Javabeanobject v = (javabeanobject) clz.newinstance ();}} /** * @param args */public static void main (string[] args) {//TODO auto-generated method Stubtestoneclassload test = new Testoneclassload (); try {test.testoneclassload ();} catch (Exception e) {//TODO auto-generated catch Blocke.printstacktrace ();} }}

Run with the following name:



Java-classpath.;.. /lib/javassist.jar-xx:permsize=2m-xx:maxpermsize=4m-xx:+printgcdetails Com.oscar999.performance.JVMTune.TestOneClassLoad



Persistent generation overflow, full GC in this case, the metadata of the class cannot be reclaimed.

In fact, if the virtual machine confirms that all instances of the class have been reclaimed and the ClassLoader that loaded the class has been reclaimed, the GC is likely to reclaim that type.

If you add a class Myclassloader

Package Com.oscar999.performance.jvmtune;public class Myclassloader extends ClassLoader {}

Testoneclassload modified into:

Package Com.oscar999.performance.jvmtune;import javassist. Cannotcompileexception;import javassist. Classpool;import javassist. Ctclass;import javassist. Notfoundexception;public class Testoneclassload {static Myclassloader C1 = new Myclassloader ();p ublic void Testoneclassload () throws Cannotcompileexception, Notfoundexception, Instantiationexception, IllegalAccessException {for (int i = 0; i < Integer.max_value; i++) {Ctclass c = Classpool.getdefault (). Makeclass ("Geym" +i); C.setsuperclass (Cl Asspool.getdefault (). Get ("Com.oscar999.performance.JVMTune.JavaBeanObject")); Class CLZ = C.toclass (c1,null); Javabeanobject v = (javabeanobject) clz.newinstance (); if (i%10==0) c1 = new Myclassloader ();}} /** * @param args */public static void main (string[] args) {//TODO auto-generated method Stubtestoneclassload test = new Testoneclassload (); try {test.testoneclassload ();} catch (Exception e) {//TODO auto-generated catch Blocke.printstacktrace ();} }}

There will be no problem with the above.



JVM Memory allocation parameters

1. Setting the maximum heap memory

Specified using the-XMX parameter. The maximum heap refers to the maximum size of the Cenozoic and Laosheng generations, which is the heap limit for Java applications.

See Example:

Package Com.oscar999.performance.jvmtune;import Java.util.vector;public class Testxmx {/** * @param args */public static void Main (string[] args) {//TODO auto-generated method Stubvector v = new Vector (); for (int i=1;i<=10;i++) {byte[] b = n EW Byte[1024*1024];v.add (b); System.out.println (i+ "M is Allocated");} System.out.println ("Max Memory:" +runtime.getruntime (). MaxMemory ()/1024/1024+ "M");}}
Use the following command line:

Java-xmx5m COM.OSCAR999.PERFORMANCE.JVMTUNE.TESTXMX



2. Setting the minimum heap memory

The JVM parameter-xms can be used to set the minimum heap space for the system. That is, the size of the operating system memory occupied by the JVM when it starts.

When the Java application runs, it is first allocated-XMS the specified memory size and tries to run the program in this space whenever possible. When the memory size specified by-XMS does not meet the application, the JVM will request more memory to the operating system until the memory size reaches the maximum memory specified by-XMX. If the value of-XMX is exceeded, the OutOfMemoryError exception is thrown.

If the value of the-XMS is small, then the JVM will perform more frequent GC operations to release the failed memory space in order to ensure that the system runs as much as possible within the specified memory range, thereby increasing the number of minor GC and full GC, which can have an impact on system performance.

Package Com.oscar999.performance.jvmtune;import Java.util.vector;public class Testxms {public static void main (String Args[]) {vector v = new vector (), for (int i = 1; i <=; i++) {byte[] b = new byte[1024 * 1024];v.add (b); if (V.size () = = 3) v.clear ();}}}

To run the command:

JAVA-XMX11M-XMS4M-VERBOSE:GC Com.oscar999.performance.JVMTune.TestXms

Results:



3. Set up new generation

The parameter-xmn is used to set the Cenozoic size. Setting a larger Cenozoic will reduce the size of the Laosheng generation, which has a significant impact on system performance and GC behavior. The Cenozoic size is generally set to about 1/4 to 1/3 of the entire heap space.

In the hot Spot virtual machine, the-xx:newsize is used to set the initial size of the Cenozoic, and-xx:maxnewsize is used to set the maximum value for the Cenozoic. However, in general, only setting up-XMN can meet the needs of most applications. Setting the-xmn effect is equivalent to setting the same-xx:newsize and-xx:maxnewsize.


4. Set Persistent generations

A durable generation (method area) is not part of a heap. In a hot Spot virtual machine, you can set the maximum value for a durable generation using-xx:maxpermsize, and you can set the initial size of a durable generation using-xx:permsize.

The size of the durable generation directly determines how many class definitions and constants the system can support. For applications that use dynamic bytecode generation tools such as Cglib or javassist, setting a reasonable durable generation size can help maintain system stability.


5. Set the thread stack

Line stacks is a piece of private space for threads.

In the JVM, you can use the-XSS parameter to set the size of the line stacks.


The relationship between the stack size and the number of threads.


6. Proportion allocation of heaps

-xx:survivorratio is used to set up a proportional relationship between Eden Space and s0 space in the Cenozoic. S0 and S1 spaces are also known as from space and to space, respectively.


Summary of parameters:



Garbage Collection

Garbage collection Algorithms and ideas

1. Reference counter (Reference counting)

For an object A, as long as any one object references a, the reference counter of A is incremented by 1, and when the reference is invalidated, the reference counter is reduced by 1. Object A can no longer be used as long as the value of the reference counter for object A is 0.

But due to the mutual reference between the garbage objects, so that the garbage collector is not recognized, causing a memory leak


Therefore, in the Java language, simply using the reference counter algorithm to implement garbage collection is not feasible.


2. Tag-purge algorithm (mark-sweep)

The garbage collection is divided into two phases: the tagging phase and the purge phase.

A feasible implementation is to mark all the objects that can be reached from the root node, first through the root node, in the tagging phase. Therefore, an object that is not marked is a garbage object that is not referenced. Then, in the purge phase, all unmarked objects are cleared. The biggest problem that the tag-cleanup algorithm can produce is space fragmentation.



3. Copy Algorithm (Copying)

Compared with the tag-purge algorithm, the replication algorithm is a fairly efficient method of recycling. The core idea is to divide the original memory space into two pieces, one at a time, to copy the memory objects being used into unused memory blocks at garbage collection, and then clear all objects in the memory block in use, swap the two memory roles, and complete the garbage collection.

However, the cost of the replication algorithm is the disadvantage of the system in the half-passbook, so the simple copy algorithm is very difficult to accept.


4. Tag-compression algorithm (MARK-COMPACT)

Tag-compression algorithm is an old-age recovery algorithm, which makes some optimizations on the basis of the tag-purge algorithm, and the tag-compression algorithm, like the tag-purge algorithm, first marks all the objects that can be reached by starting from the root node.


5. Incremental algorithm (Incremental collecting)

If all the garbage is processed at once and the system needs to be paused for a long time, then the garbage collection thread and the application thread can be executed alternately. Each time, the garbage collection thread collects only a small area of memory space, then switches to the application thread, so repeatedly, knowing that garbage collection is complete.


6. Sub-generational (generational collecting)

The memory interval is divided into several pieces according to the characteristics of the object, and the different recovery algorithms are used to improve the efficiency of garbage collection according to the characteristics of each memory interval.



Classification of garbage collectors



Metrics for evaluating GC policies

Throughput: The ratio of the time spent by an application to the total elapsed time of the system during the lifetime of the application.

Garbage collector Load: The garbage collector load is the ratio of the time spent by the garbage collector to the total system uptime

Pause time: The application's pause time when the garbage collector is running.

Garbage collection frequency: Refers to how long the garbage collector runs.

Reaction time: When an object is called garbage, the amount of memory space it occupies will be released.

Heap allocation: Different garbage collector may have different ways of allocating memory. A good garbage collector should have a reasonable breakdown of heap memory intervals.


common tuning cases and methods

1. Reserving new objects in the next generation

The cost of full GC is much higher than minor GC, so it is wise to allocate objects to the next generation whenever possible. While in most cases the JVM will attempt to allocate objects in the Eden area, it is likely to have to compress some of the young objects early into the old age due to space constraints. Therefore, in the JVM parameter tuning, the application can be allocated a reasonable new generation of space to minimize the situation of the newly-accessed objects directly into the old age.

Look at the following example,

Package Com.oscar999.performance.jvmtune;public class Putineden {/** * @param args */public static void main (string[] args ) {//TODO auto-generated method stubbyte[] b1,b2,b3,b4;b1 = new BYTE[1024*1204];B2 = new BYTE[1024*1204];B3 = new byte[10 24*1204];B4 = new byte[1024*1204];}}

When the Cenozoic size is set to 1 m, the following command is run:


Java-xx:+printgcdetails-xmx20m-xms20m-xmn1m Com.oscar999.performance.JVMTune.PutInEden



When the Cenozoic is set to 6 m,

Java-xx:+printgcdetails-xmx20m-xms20m-xmn6m Com.oscar999.performance.JVMTune.PutInEden



Similarly, parameters such as-xx:newratio can also be used to specify the Cenozoic size. By setting up a large new generation of reserved objects, setting a reasonable survivor area and increasing the utilization rate of the survivor area, young objects can be kept in the Cenozoic. In general, when the space in the survivor area is not enough, or the occupancy reaches 50%, the object will enter the old age.


2. Large objects into the old age

Large objects appearing in the Cenozoic are likely to disrupt the Cenozoic GC and destroy the original structural objects of the Cenozoic. Because trying to allocate large objects in the new generation is likely to lead to insufficient space, the JVM has to move young objects from the new generation to the old age in order to have enough space to accommodate large objects. Because large objects occupy much space, it may be necessary to move a large number of small young objects into the old age, which is quite detrimental to the GC's old saying.

Large objects can be allocated directly to the old age, maintaining the integrity of the new generation object structure to improve the efficiency of GC.

In the process of software development, the use of short-lived large objects should be avoided as much as possible.

You can use the parameter-xx:pretenuresizethreshold to set the threshold for large objects to enter the old age directly. When the size of the object exceeds this value, it is allocated directly in the old age.

Note: This parameter is valid only for the serial collector and the Cenozoic parallel collector, which is not recognized by the parallel collector.

See Example:

Package Com.oscar999.performance.jvmtune;public class Bigobj2old {/** * @param args */public static void main (string[] Arg s) {//TODO auto-generated method stubbyte[] b1;b1 = new byte[1024*1024];}}
Use the following command:

java-xx:+printgcdetails-xmx20m-xms20m Com.oscar999.performance.JVMTune.BigObj2Old


As you can see, the object is assigned to the new generation and is almost full of the new generation.

If you use the following command:

java-xx:+printgcdetails-xmx20m-xms20m-xx:pretenuresizethreshold=1000000 Com.oscar999.performance.JVMTune.BigObj2Old


As you can see, the 1MB byte array has been allocated in the old age.


3. Set the age of the object into the old years

In general, young objects are stored in the Cenozoic, and old age objects are stored in the old age. To do this, the virtual machine maintains an age for each object.

If the object is in the Eden area and survives after a GC, it is moved to the Survivior area, the object age is 1, and after the object is still alive after each GC, the age is added by 1. When the age of the object reaches the threshold, it is moved into the old age and becomes the age object.

The maximum value of this threshold is set by the parameter:-xx:maxtenuringthreshold, whose default value is 15.


4. Stability and vibration of the heap size

In general, a stable heap size is beneficial for garbage collection. The way to get a stable heap size is to make the size of the-XMS and-xmx consistent, that is, the largest heap and the smallest heap. If this is set, the heap size is constant while the system is running, and a stable heap space can reduce the number of GC times. Therefore, many server-side applications set the maximum heap and the minimum heap to the same value.

A stable heap size can reduce the number of GC times, but it also increases the time of each GC. Let the heap size in a range of shocks, when the system to use large memory, compressed heap space, so that the GC should be a smaller heap, can speed up a single GC. Based on this, the JVM also provides two parameters for compressing and extending the heap space:

-xx:minheapfreeratio: Sets the minimum idle scale for heap space. The default is 40. When the free memory in the heap space is less than this value, the JVM expands the heap space.

-xx:maxheapfreeratio: Sets the maximum idle scale for heap space. The default is 70. When the free memory in the heap space is greater than this value, the heap space is compressed and a smaller heap is obtained.

When-xms and-xmx are equal, both parameters of-xx:minheapfreeration and-xx:maxheapfreeratio are invalid.


5. Throughput Priority Cases

Minimize the total time that the system performs garbage collection.

Look at the following settings:


6. Use large-page case

In a Solaris system, the JVM can support the use of large pages, using large memory paging to enhance the memory addressing capabilities of the CPU, thereby improving system performance



Preface

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Java Performance Optimization Series 3.1[JVM tuning]

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.