文档章节

JIT编程与方法内联

爱吃窝窝头
 爱吃窝窝头
发布于 10/22 09:28
字数 1075
阅读 11
收藏 0

JIT的比较冷门,首先你要读一下这两篇 帖子:

《面向JIT编程-方法内联》 https://blog.csdn.net/u012834750/article/details/79488572

《浅谈对JIT编译器的理解》 https://www.cnblogs.com/insistence/p/5901457.html

后面就是实战的内容了:

一、我们先看方法内联:

根据帖子里面说的,方法内联只会发生在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
}

二、下面我们来看一下JIT编译:

先看下面代码:

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编译的参数打印出来。

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)

© 著作权归作者所有

爱吃窝窝头
粉丝 1
博文 44
码字总数 16032
作品 0
南京
私信 提问
《Effective C#》读书笔记——条目11:理解短小方法的优势

在应用程序开发过程中,开发者都力求写出更加高效的代码。但是当你想手工为C#编译器优化代码时,你的种种优化可能反倒会阻碍JIT进行更加高效的优化。因此,我们最好尽可能的写出最清晰的代码...

吞吞吐吐的
2017/09/13
0
0
Java JIT性能调优

Java JIT性能调优 戎码一生2016-07-18219 阅读 Javajvmjava JVM自动监控这所有方法的执行,如果某个方法是热点方法,JVM就计划把该方法的字节码代码编译成本地机器代码,同时还会在后续的执行...

戎码一生
2016/07/18
0
0
JVM优化之逃逸分析与分配消除

在Java Magazine的前几期文章中,我们介绍了just-in- time (JIT) 编译技术的一些理论基础,以及如何使用Java Microbenching Harness(JMH)和开源工具JITWatch来进行可视化分析,以便搞清楚H...

01/02
0
0
Effective C# 摘录(4) - 创建二进制组件

30.尽可能实现CLS兼容的程序集。 Prefer CLS-Compliant Assemblies。 必须遵从两个规则:1.所有公共的和受保护的成员上的参数和返回值的类型都必须是与CLS兼容的[assembly:CLSCompliant(true...

吞吞吐吐的
2017/09/12
0
0
怎样让你的代码更好的被JVM JIT Inlining

怎样让你的代码更好的被JVM JIT Inlining 戎码一生2016-07-3177 阅读 javaJavajvm JVM JIT编译器优化技术有近100中,其中最最重要的方式就是内联(inlining)。方法内联可以省掉方法栈帧的创...

戎码一生
2016/07/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

前端的一些雕虫小技,从100%和滚动条说起

1、100%和滚动条 当我们在css中把html和body同时设为100%时,会出现滚动条 html, body { width: 100%; height: 100%; } 原因是html和b...

wphmoon
35分钟前
6
0
电力区块链应用案例【2019】

随着区块链技术的日益普及,出现了大量创业企业尝试使用区块链技术来解决能源与电力行业中存在的问题。在本文中,我们将介绍其中的三个能源区块链项目。 能源行业以价格不透明著称:消费者很...

汇智网教程
56分钟前
7
0
聊聊rocketmq的adjustThreadPoolNumsThreshold

序 本文主要研究一下rocketmq的adjustThreadPoolNumsThreshold DefaultMQPushConsumer rocketmq-client-4.5.2-sources.jar!/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.ja......

go4it
今天
10
0
关于早起

早起是非常好的事情,但是像如果前一天睡得晚,或者第二天早上是非常冷的时候,那就不是很美好了。 但是本身早起是一件非常棒的事情,我记得我每次早起 如果不觉得困的话,世界是那么安静,脑...

T型人才追梦者
今天
7
0
Java输入输出

JDK中的InputStream/OutputStream构成了IO输入输出继承层次的基础。它们都是面向字节序列的,每次可以从序列中读入或者写出一个字节或者指定大小的字节数组。但是面向字节流的输入输出不便于...

ytuan996
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部