JIT編程與方法內聯

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)
相關文章
相關標籤/搜索