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)
相关文章
相关标签/搜索