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)