JIT编程与方法内联

Wesley13
• 阅读 549

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)
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Stella981 Stella981
2年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Wesley13 Wesley13
2年前
P2P技术揭秘.P2P网络技术原理与典型系统开发
Modular.Java(2009.06)\.Craig.Walls.文字版.pdf:http://www.t00y.com/file/59501950(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.t00y.com%2Ffile%2F59501950)\More.E
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Stella981 Stella981
2年前
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法参考文章:(1)Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.codeprj.com%2Fblo
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这