JIT的比较冷门,首先你要读一下这两篇 帖子:html
《面向JIT编程-方法内联》 https://blog.csdn.net/u012834750/article/details/79488572java
《浅谈对JIT编译器的理解》 https://www.cnblogs.com/insistence/p/5901457.html编程
后面就是实战的内容了:app
1、咱们先看方法内联:eclipse
根据帖子里面说的,方法内联只会发生在private方法中,那咱们来看一下是否是这样。函数
public static void main(String[] args) throws ClassNotFoundException { for (int i = 0; i < 1000000; i++) { name(i); } } public static void name(int k) { for (int i = 0; i < k; i++) { name1(i); } } private static void name1(int i) { i = i * 100; } }
用javac命令编译后,用javap命令查看汇编状况,发现私有函数name1()被内联,咱们知道内联最大的好处就是去掉了压栈 弹栈,提高性能。性能
D:\software\eclipse\eclipse-workspace_solo\TESTTT\src>javap -c Main2 Compiled from "Main2.java" public class Main2 { public Main2(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]) throws java.lang.ClassNotFoundException; Code: 0: iconst_0 1: istore_1 2: iload_1 3: ldc #2 // int 1000000 5: if_icmpge 18 8: iload_1 9: invokestatic #3 // Method name:(I)V 12: iinc 1, 1 15: goto 2 18: return public static void name(int); Code: 0: iconst_0 1: istore_1 2: iload_1 3: iload_0 4: if_icmpge 17 7: iload_1 8: invokestatic #4 // Method name1:(I)V 11: iinc 1, 1 14: goto 2 17: return }
2、下面咱们来看一下JIT编译:ui
先看下面代码:spa
public class Main2 { public static void main(String[] args) throws ClassNotFoundException { for (int i = 0; i < 1000000; i++) { name(i); } } public static void name(int k) { for (int i = 0; i < k; i++) { name1(i); } } private static void name1(int i) { i = i * 100; } }
编译后,咱们进行运行,但在运行的时候,加上:-XX:+PrintCompilation 参数,这样会把JIT编译的参数打印出来。.net
D:\software\eclipse\eclipse-workspace_solo\TESTTT\src>java -XX:+PrintCompilation Main2 71 1 3 java.lang.String::hashCode (55 bytes) 72 2 3 java.lang.String::equals (81 bytes) 73 3 4 java.lang.String::charAt (29 bytes) 73 4 3 java.lang.String::<init> (82 bytes) 74 10 4 java.lang.String::length (6 bytes) 74 6 3 java.lang.Character::toLowerCase (9 bytes) 74 11 n 0 java.lang.System::arraycopy (native) (static) 75 7 3 java.lang.CharacterData::of (120 bytes) 75 8 3 java.lang.CharacterDataLatin1::toLowerCase (39 bytes) 76 9 3 java.lang.CharacterDataLatin1::getProperties (11 bytes) 76 5 3 java.util.Arrays::copyOfRange (63 bytes) 80 12 3 java.lang.Object::<init> (1 bytes) 81 13 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes) 82 15 3 java.lang.String::indexOf (70 bytes) 82 17 1 java.lang.Object::<init> (1 bytes) 82 12 3 java.lang.Object::<init> (1 bytes) made not entrant 83 14 3 java.lang.AbstractStringBuilder::append (29 bytes) 84 18 3 java.io.WinNTFileSystem::isSlash (18 bytes) 84 19 s 3 java.lang.StringBuffer::append (13 bytes) 85 16 3 java.lang.StringBuilder::append (8 bytes) 85 20 3 java.lang.AbstractStringBuilder::append (50 bytes) 88 21 3 Main2::name1 (6 bytes) 88 22 3 Main2::name (18 bytes) 88 23 1 Main2::name1 (6 bytes) 89 24 % 4 Main2::name @ 2 (18 bytes) 90 21 3 Main2::name1 (6 bytes) made not entrant 91 25 4 Main2::name (18 bytes) 91 22 3 Main2::name (18 bytes) made not entrant 92 26 % 3 Main2::main @ 2 (19 bytes) 93 27 3 Main2::main (19 bytes) 93 28 % 4 Main2::main @ 2 (19 bytes) 94 26 % 3 Main2::main @ -2 (19 bytes) made not entrant 95 28 % 4 Main2::main @ -2 (19 bytes) made not entrant
经过观察,咱们发现name和name1函数都被进行JIT编译了,由于他们都是高热点函数,而且执行次数较多。
那么咱们来看一下,若是执行次数比较少的时候,是什么状况呢?咱们修改一下代码:
public class Main2 { public static void main(String[] args) throws ClassNotFoundException { for (int i = 0; i < 100; i++) { // 这个地方1000000 变成了100 name(i); } } public static void name(int k) { for (int i = 0; i < k; i++) { name1(i); } } private static void name1(int i) { i = i * 100; } }
修改后,咱们再执行,在看JIT编译函数,你会发现name和name1都不见了,这也验证了JIT是运行时,C1或者C2编译器发现热点函数,进行从新编译起到做用。
D:\software\eclipse\eclipse-workspace_solo\TESTTT\src>java -XX:+PrintCompilation Main2 73 1 3 java.lang.String::hashCode (55 bytes) 74 2 3 java.lang.String::equals (81 bytes) 75 3 4 java.lang.String::charAt (29 bytes) 75 4 3 java.lang.String::<init> (82 bytes) 75 11 n 0 java.lang.System::arraycopy (native) (static) 77 10 4 java.lang.String::length (6 bytes) 77 6 3 java.lang.Character::toLowerCase (9 bytes) 78 7 3 java.lang.CharacterData::of (120 bytes) 78 8 3 java.lang.CharacterDataLatin1::toLowerCase (39 bytes) 79 9 3 java.lang.CharacterDataLatin1::getProperties (11 bytes) 79 5 3 java.util.Arrays::copyOfRange (63 bytes) 83 12 3 java.lang.Object::<init> (1 bytes) 83 13 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes) 84 15 3 java.lang.String::indexOf (70 bytes) 85 18 1 java.lang.Object::<init> (1 bytes) 85 12 3 java.lang.Object::<init> (1 bytes) made not entrant 86 14 3 java.lang.AbstractStringBuilder::append (29 bytes) 87 17 3 java.lang.StringBuilder::append (8 bytes) 88 16 3 java.io.WinNTFileSystem::isSlash (18 bytes) 88 19 s 3 java.lang.StringBuffer::append (13 bytes) 93 20 3 Main2::name1 (6 bytes)