JIT编程与方法内联

Wesley13
• 阅读 404

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)
点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
5个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。languageJavaScript"name":"vuecliversion2","version":"1.0.0","desc
浅梦一笑 浅梦一笑
5个月前
初学 Python 需要安装哪些软件?超级实用,小白必看!
编程这个东西是真的奇妙。对于懂得的人来说,会觉得这个工具是多么的好用、有趣,而对于小白来说,就如同大山一样。其实这个都可以理解,大家都是这样过来的。那么接下来就说一下python相关的东西吧,并说一下我对编程的理解。本人也是小白一名,如有不对的地方,还请各位大神指出01名词解释:如果在编程方面接触的比较少,那么对于软件这一块,有几个名词一定要了解,比如开发环
技术小男生 技术小男生
5个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi/etc/profile2:按字母键i进入编辑模式,在最底部添加内容:JAVAHOME/opt/jdk1.8.0152CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jarPATH$JAVAHOME/bin:$PATH3:生效配置
光头强的博客 光头强的博客
5个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
5个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
小森森 小森森
5个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
5个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
5个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
NVIDIA安培架构下MIG技术分析
关键词:NVIDIA、MIG、安培一什么是MIG2020年5月,NVIDIA发布了最新的GPU架构:安培,以及基于安培架构的最新的GPU:A100。安培提供了许多新的特性,MIG是其中一项非常重要的新特性。MIG的全名是MultiInstanceGPU。NVIDIA安培架构中的MIG模式可以在A100GPU上并行运行七个作业。多实
helloworld_28799839 helloworld_28799839
5个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue