JIT and escape analysis

The previous mentioned back-end compiler compiler theory, it is the class files compiled into a byte instruction process, in this process, you can take interpreted and compiled execution two roads:

1. If a single walk interpreted, each executing a method, should explain it again, will be slower on efficiency

javac the java source files translated into class files, and class files are all Java byte code. So, JVM in the class file is loaded later, for those byte codes, one by one out, one by one implementation of this method is interpreted.

2. If the compiler to perform all go, then special memory consumption, each went on to compile a method again, and into memory, then the question is, of precious memory, such that the low frequency of execution code compiler takes up memory

Another is to recompile the Java bytecode optimization, machine code generated, so that CPU executed directly. This series out code will be more efficient. In general, we do not have to put all the Java methods are compiled into machine code, just need to call the most frequently occupy CPU longest way to find out compile it into machine code. This most frequently invoked Java method is what we often say that the hot method (Hotspot, maybe the name of the virtual machine is from here). This demand compiled at runtime way to Just In Time.

The current mainstream commercial HotSpot virtual machine is using Mixed mode (with the use of an interpreter and compiler are mixed mode), may use the technology JIT (Just In Time) - time compilation, JIT introduction, is a optimization of items compiled, looking at the efficiency and the balance in the JVM memory space. JIT will do a lot of code optimization. The purpose of which is to reduce part of the optimization of the allocation of memory heap pressure, which is an important technique called escape analysis.

See the Nuggets one pair escape analysis said very thorough article, carried: juejin.im/post/5b4d47...

What is the escape analysis

The basic escape analysis is an analysis target dynamic scoping behavior: When an object is defined in the method, it may be referenced by external means, such as a call parameter passing to other places, the method referred to escape.

public static StringBuffer craeteStringBuffer(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb;
}

public static String craeteStringBuffer(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb.toString();
}

复制代码

The first code sb to escape, while the second segment of code sb no escape.

Use escape analysis, the compiler can optimize code as follows:

A synchronization omitted. If an object is found that can only be accessed from one thread to, then for the operation of the object can not be considered synchronized.

Second, the stack was converted to the stack allocation. If an object is allocated in the subprogram, to make the pointer to that object never escape, stack allocation candidate object may be, rather than heap allocation.

Third, the separation object replacement or scalar. Some objects may not be required as a continuous presence of a memory structure may also be accessed, then the part (or all) of the object may not be stored in memory, but is stored in the CPU registers.

In the Java code runs through the JVM parameter specifies whether to open the escape analysis,

-XX: + DoEscapeAnalysis: indicate on escape analysis

-XX: -DoEscapeAnalysis: means closed escape analysis

Synchronization is omitted

From jdk 1.7 has the default Start escape analysis when dynamic compilation sync blocks, JIT compiler can escape analysis to help determine the lock target sync block used, if only one thread can be accessed without being published to other threads. If the synchronization block lock objects used proved to be only one thread accessed through this analysis, the JIT compiler will cancel this part of the code synchronized at the time of compiling this sync block. The cancellation of the synchronization process is called synchronous omitted, also known as lock eliminated. As the following code:

public void f() {
    Object hollis = new Object();
    synchronized(hollis) {
        System.out.println(hollis);
    }
}
复制代码

Hollis code to lock the object, but the object life cycle hollis only f () method, and can not be accessed by other threads, so the JIT compilation phase will be optimized away. Optimized to:

public void f() {
    Object hollis = new Object();
    System.out.println(hollis);
}
复制代码

Therefore, when using synchronized, and if after JIT escape through the analysis found no thread-safety issues, it would do lock eliminated.

Scalar replacement

Scalar (the Scalar) refers to a data can no longer be broken down into smaller data. Java in the original data type is a scalar. In contrast, those data may also be called a decomposed amount of polymerization (Aggregate), Java objects is the amount of the polymerization, since he may be decomposed into other aggregate and scalar quantity. In JIT stage, if after escape analysis, found that an object can not be accessed outside, then through JIT optimizations, this object will be broken down into a number of members of several variables contained therein instead. This process is replaced by a scalar.

public static void main(String[] args) {
   alloc();
}

private static void alloc() {
   Point point = new Point(1,2);
   System.out.println("point.x="+point.x+"; point.y="+point.y);
}
class Point{
    private int x;
    private int y;
}
复制代码

In the above code, the object does not escape the point alloc method, and the object point can be broken down into scalar. So, JIT will not directly create a Point object, but direct use of two scalar int x, int y instead of a Point object. The above code, after replacing scalar, becomes:

private static void alloc() {
   int x = 1;
   int y = 2;
   System.out.println("point.x="+x+"; point.y="+y);
}
复制代码

Can be seen, the amount of the polymerization Point after the escape analysis, and found that he did not escape, it is replaced with the amount of polymerization into two. Scalar replacement then what good is it? That can greatly reduce the heap memory usage. Because once the do not need to create an object, then it is no longer a need to allocate heap memory.

Scalar replacement is allocated on the stack provides a good foundation.

Allocated on the stack

In the Java virtual machine, Java objects are allocated on the heap memory, which is a common sense. However, there is a special situation, that is, if after the escape analysis found that an object did not escape the method, then can be optimized to be allocated on the stack. This eliminates the need to allocate memory on the heap, there is no need for garbage collection up.

For more information about the distribution of the stack, can refer to objects and arrays are not allocated on the heap memory

Here, still have to say something simple, in fact, the existing virtual machine, and not allocated on the true meaning of the stack, the objects and arrays are not allocated on the heap memory of example, the object is not allocated on the heap, in fact, scalar replacement is achieved.

Escape analysis is not mature treatise on escape analysis published in 1999, but only until JDK 1.6 implementation, and the technology to now also not very mature. The fundamental reason for this is no guarantee that escape analysis of performance will be able to consume higher than his consumption. Even after escape analysis can be done scalar replacement, allocated on the stack, and lock eliminated. But their escape analysis also requires a complex set of analysis, it is also a relatively time-consuming process.

An extreme example is the analysis after the escape, an object is not found no escape. That escape this analysis process is wasted. While the technology is not very mature, but he is also a time compiler technology is a very important means of optimization.

Guess you like

Origin juejin.im/post/5d36ebdff265da1ba915bf20