In-depth understanding of Java virtual Machines-Personal summary

Source: Internet
Author: User
Tags array definition

JVM Memory Area

When we write programs, we often encounter issues such as oom (out of memory) and memory leaks. To avoid these problems, we must first have a specific understanding of the JVM's memory partitioning. The JVM divides the memory mainly into: Method area, virtual machine stack, local method stack, heap, program counter. The JVM runtime data area is as follows:

Program counter

The program counter is a thread-private area, well understood, each thread of course has to have a counter to record the current execution to that command. It takes up less memory space and can be seen as the line number indicator of the byte code executed by the current thread. If the thread is executing a Java method, this counter records the executing virtual machine bytecode instruction address, and if the native method is executed, the value of this counter is null (Undefined). This memory area is the only area in the Java Virtual Machine specification that does not stipulate any outofmemoryerror conditions.

Java Virtual Machine stack

As with program counters, Java Virtual machine stacks are thread-private. Its life cycle is the same as the thread. How do you understand virtual machine stacks? Essentially, it's a stack. Inside the stored element is called the stack frame, the stack frame seems very complex appearance, in fact it is very simple! It contains the context of a function, which holds some data about the function being executed. The data required for executing a function is nothing more than a local variable table (a variable inside a function), an operand stack (required for execution of engine calculations), a method exit, and so on.

Each time the execution engine calls a function, it creates a stack frame for the function and joins the virtual machine stack. In a different sense, each function from the call to the end of execution, is actually a stack frame corresponding to the stack and out of the stack.

Note the two exceptions that can occur in this area: one is Stackoverflowerror, and this exception is thrown when the current thread requests a stack depth that is greater than the depth allowed by the virtual machine. Making this exception is simple: recursive a function over and over again, and end up with stack overflow errors (stackoverflowerror). Another exception is the OutOfMemoryError exception, when the virtual machine stack can be dynamically extended (most of the current virtual machine can be), if you cannot request enough memory will throw OutOfMemoryError, how to make a virtual machine stack oom, refer to the code:

public void stackLeakByThread(){    while(true){ new Thread(){ public void run(){ while(true){ } } }.start() }}

This code is risky, may cause the operating system suspended animation, please use caution ~ ~ ~

Local method Stack

The local method stack is very similar to the virtual machine stack, and the difference is that the virtual machine stack serves the Java code method, and the local method stack serves the native method. As with the virtual machine stack, the local method stack throws Stackoverflowerror and OutOfMemoryError exceptions.

Java heap

The Java heap can be said to be the largest chunk of memory in a virtual machine. It is the area of memory shared by all threads, and almost all instance objects are stored in this area. Of course, falling asleep JIT compiler development, all objects on the heap distribution gradually become less "absolute".

The Java heap is the primary area of garbage collector management. Since the collector is basically a generational collection algorithm, all Java heaps can be subdivided into: the new generation and the old age. In detail, the new generation is divided into: Eden Space, from Survivor space, to survivor space. The OutOfMemoryError exception is thrown when the heap can no longer be expanded.

Method area

The method area holds class information, constants, static variables, and so on. The method area is a shared area for each thread, and it's easy to understand that when we write Java code, each line degree can access static variable objects of the same class. Because of the reflection mechanism, it is difficult for a virtual machine to speculate that such information is no longer in use, so the recovery of this area is difficult. In addition, for this area is mainly for the constant pool recovery, it is worth noting that JDK1.7 has shifted the constant pool into the heap. Similarly, OutOfMemoryError are thrown when the method area does not meet the memory allocation requirements.
The Manufacturing method area memory Overflow, note, must be in JDK1.6 and previous versions before the method area overflow, the reason behind the explanation, before execution, you can put the parameters of the virtual machine-xxpermsize and-xx:maxpermsize limit the method area size.

List<String> list =new ArrayList<String>();int i =0;while(true){ list.add(String.valueOf(i).intern());} 

The Java.lang.OutOfMemoryError:PermGen space exception is thrown after running.
Explain that the intern () function of string is placed into a constant pool if the current string does not exist in the constant pool. The above code constantly adds strings to the constant pool, which will eventually result in out-of-memory, throwing an oom in the method area.

The

explains why the above code must be run before JDK1.6. As we mentioned earlier, after JDK1.7, put the constant pool into the heap space, which leads to the function of the intern () function is different, specifically how to different methods, and look at the following code:

string str1 =new StringBuilder (.append (" Chao ") .out.println (str1 .intern () ==str1)  "ja") .append ( "va") .tostring () .out.println (str2 .intern () ==str2)              

This code is different from the results of the JDK1.6 and JDK1.7 runs. JDK1.6 result is: False,false, JDK1.7 The result is true, false. The reason is: JDK1.6, the Intern () method will be the first time a string instance encountered is copied into a constant pool, and a reference to the string in the constant pool is returned, and the string instance created by StringBuilder is above the heap, so it is not necessarily the same reference and returns FALSE. In JDK1.7, intern no longer replicates the instance, only the reference to the first occurrence of the instance is saved in the constant pool, so the reference returned by intern () and the string instance created by StringBuilder are the same. Why is the comparison returned to str2 false? This is because when the class is loaded internally in the JVM, there is already a string of "Java" that does not conform to the "first occurrence" principle and therefore returns false.

Garbage collection (GC)

In the garbage collection mechanism of the JVM, judging whether an object is dead or not, it is not based on whether or not the object has references to it, but through accessibility analysis. References between objects can be abstracted into a tree structure, with root (GC Roots) as a starting point, searching from these roots, searching through a chain called a reference chain, and when an object is connected to a GC Roots without any reference chain, it proves that the object is unavailable and that the object is judged to be a recyclable object.

What about those objects that can be used as GC roots? There are mainly the following types:

1. The object referenced in the virtual machine stack (local variable table in the stack frame).
2. The object referenced by the class static property in the method area.
3. Objects referenced by constants in the method area
4. The object referenced by the JNI (that is, the generally said native method) in the local method stack.

In addition, Java provides soft and weak references, which are objects that can be reclaimed by the virtual machine at any time, and we will make some objects that compare memory but may be used later, such as the bitmap object, which can be declared as soft reference goods weak reference. Note, however, that each time you use this object, you need to indicate whether it is null to avoid errors.

Three common garbage collection algorithms

1. Tag-Clear algorithm

First, through the accessibility analysis of the recyclable objects tagged, and then the unified collection of all tagged objects, marking process is actually the process of accessibility analysis. There are 2 deficiencies in this approach: efficiency issues, the efficiency of labeling and clearing two processes is not high, and the other is the spatial problem, which results in a large amount of discontinuous memory fragmentation after the mark is cleared.

2. Copying algorithms

To solve the efficiency problem, the replication algorithm divides the memory into two blocks of the same size, using only one piece at a time. When this memory is exhausted, the surviving object is copied to the other memory. Then clean up the memory that has been used once. This makes it possible to recycle only half of the area at a time, and memory allocations are not considered memory fragmentation.

However, the cost is unacceptable and requires sacrificing general memory space. The study found that most of the objects were "dying", so there was no need to install 1:1 scale memory space, but instead to divide the memory into a larger Eden space and two smaller survivor space, each time using Eden space and a piece of survivor space, The default scale is eden:survivor=8:1. This is how the Cenozoic regions are divided, each time an instance is allocated in Eden and a piece of Survivor, and when it is reclaimed, the surviving object is copied to the remaining other Survivor. Only 10% of the memory is wasted, but the efficiency is high. When the rest of the survivor memory is insufficient, you can go to the old memory allocation guarantee. How to understand the allocation of security, in fact, when the memory is not enough, to the old memory space allocation, and then wait for the new generation of memory slowed down, the memory back to the old age, to maintain the eden:survivor=8:1 in the Cenozoic. In addition, two Survivor have their own name: from Survivor, to Survivor. The identities are often swapped, that is, sometimes this memory is allocated with Eden, sometimes in another. Because they often replicate with each other.

3. Labeling-Sorting algorithm

The tagging algorithm is simple to tag objects that need to be recycled, and then move all the surviving objects to one end of the memory. The advantage is that memory fragmentation is avoided.

Class loading mechanism

Class from being loaded into virtual machine memory, to unloading out of memory, the entire lifecycle includes: load, validate, prepare, parse, initialize, use, and unload seven phases.

The order in which the 5 phases are loaded, validated, prepared, initialized, and unloaded is determined. The parsing phase is not necessarily: it can be started after the initialization phase in some cases, in order to support Java runtime bindings.

About initialization: The JVM specification explicitly stipulates that there are only 5 cases where the initialization of the class must be performed (loading, validating, preparing for the nature of this before it happens):
1. Encounter new, Getstatic, putstatic, Invokestatic, if the class is not initialized, it must be initialized, these instructions are: new object, read static variable, set static variable, call static function.
2. When you use the Java.lang.reflect package method to make a reflection call to a class, you need to initialize the class if it is not initialized.
3. When initializing a class, if you find that the parent class is not initialized, you need to trigger the initialization of the parent class first.
4. When the virtual machine starts, the user needs to develop a main class of execution (the class that contains the main function), and the virtual opportunity initializes the class first.
5. However, with JDK1.7 dynamic language support, if a methodhandle instance finally resolves the result is ref_getstatic, ref_putstatic, ref_invokestatic method handle, And the class that corresponds to the method handle is not initialized, it is triggered first.

It is also important to note that using subclasses to refer to the static fields of the parent class does not cause subclasses to initialize:

PublicClasssuperclass{public static int Value=123; static{System.out.printLn ( "superclass init!");}} public class subclass extends SuperClass{static{System.out.println ( "subclass init!");}} public class test{public static void main (string[] args) {System.out.println (Subclass.value);}}    

Last only print: Superclass init!
For static variables, only classes that directly define the field are initialized, so referencing a static variable defined in the parent class by a subclass class will only trigger the parent class to initialize without triggering the subclass initialization.

Referencing a class through an array definition does not trigger initialization of this class:

public class Test{    public static void main(String[] args){ SuperClass[] sca=new SuperClass[10]; }}

Constants are stored in the caller's constant pool at compile time and are not directly referenced to the class that defines the constants, so class initialization that defines the constants is not triggered, and the sample code is as follows:

public class ConstClass{    public static final String HELLO_WORLD="hello world"; static { System.out.println("ConstClass init!"); }}public class Test{ public static void main(String[] args){ System.out.print(ConstClass.HELLO_WORLD); }}

The above code does not appear Constclass init!

Load

The loading process mainly does the following 3 things
1. Obtain a binary stream of this class by using the fully qualified name of a class
2. The static storage structure represented by this byte stream is transformed into a run-time data structure of the method area
3. Generate a Java.lang.Class object representing this class in memory as a variety of data access portals for the class of the method area.

Verify

This phase is primarily to ensure that the class file byte stream contains information that meets the requirements of the current virtual machine and does not compromise the security of the virtual machine itself.

Get ready

The prep phase is a phase that formally allocates memory for class variables and sets the initial value of class variables, and the memory used by these variables is allocated in the method area. First, allocating memory at this time only includes class variables (variables that are modified by static), not instance variables. Instance variables are allocated in the Java heap along with the objects as they are instantiated. Second, the initial value "typically" is a 0 value of the data type, assuming that a class variable is defined as

public static int value=123;

The initial value of the variable value after the prep phase is 0, not 123, because no Java method has been executed, and value assignment 123 is stored in the class constructor < Clinit > () method after the program is compiled.
Analytical

The parsing phase is the process of replacing the symbolic reference of a constant pool in a virtual machine with a direct reference.

Initialization

Class initialization is the last step in class loading, and the rest of the actions are virtual machine-driven and controlled in addition to the load phase in which the user can participate through the custom ClassLoader. In the initialization phase, the Java program code is defined in the actual execution class.

During the preparation phase, variables have already been assigned the initial value of the system requirements, and during the initialization phase, class variables are initialized according to the subjective plan developed by the programmer through the program. The initialization process is actually the process of executing the class constructor < Clinit > () method.

The < Clinit > () method is generated by the compiler's automatic collection of assignment actions for all class variables in the class and statements in the static statement block. The order of collection is in the order in which the statements appear in the source file. A static statement block can only access variables defined before a static statement block, and variables defined after it may be assigned values, but cannot be accessed. As shown below:

public class Test{    static{        i=0;//給变量赋值,可以通过编译 System.out.print(i);//这句编译器会提示:“非法向前引用” } static int i=1;}

The < Clinit > () method differs from the class constructor (or instance constructor < init > ()) In that he does not need to explicitly call the parent class constructor, and the virtual opportunity guarantees that the child class's < Clinit > () method executes before the parent class's < Clinit > () has been executed.

In-depth understanding of Java virtual Machines-Personal summary

Related Article

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.