前言

在日常中工作中,我们时不时会代码进行一些优化,比如用新的算法,简化计算逻辑,减少计算量等。对于java程序来说,除了开发者本身对代码优化之外,还有一个"人"也在背后默默的优化我们的代码,这个"人"就是jvm。jvm会帮我们分析出热点代码,优化代码逻辑。其中jvm最常做的优化之一就是:方法内联优化。

方法内联

什么是方法内联?又可以叫做函数内联,java中方法可等同于其它语言中的函数。关于方法内联维基百科上面解释是:

在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。

简单通俗的讲就是把方法内部调用的其它方法的逻辑,嵌入到自身的方法中去,变成自身的一部分,之后不再调用该方法,从而节省调用函数带来的额外开支。

函数调用开销

之所以出现方法内联是因为函数调用除了执行自身逻辑的开销外,还有一些不为人知的额外开销。这部分额外的开销主要来自方法栈帧的生成、参数字段的压入、栈帧的弹出、还有指令执行地址的跳转。比如有下面这样代码:

public static void function_A(int a, int b){
//do something
function_B(a,b);
} public static void function_B(int c, int d){
//do something
} public static void main(String[] args){
function_A(1,2);
}

则代码的执行过程如下:

所以如果java中方法调用嵌套过多或者方法过多,这种额外的开销就越多。

试想一下想get/set这种方法调用:

public int getI() {
return i;
} public void setI(int i) {
this.i = i;
}

很可能自身执行逻辑的开销还比不上为了调用这个方法的额外开锁。如果类似的方法被频繁的调用,则真正相对执行效率就会很低,虽然这类方法的执行时间很短。这也是为什么jvm会在热点代码中执行方法内联的原因,这样的话就可以省去调用调用函数带来的额外开支。

这里举个内联的可能形式:

public int  add(int a, int b , int c, int d){
return add(a, b) + add(c, d);
} public int add(int a, int b){
return a + b;
}

内联之后:

public int  add(int a, int b , int c, int d){
return a + b + c + d;
}

这样除了本身的相加逻辑的开销,比内联前减少了二次调用函数带来的额外开销。

内联条件

一个方法如果满足以下条件就很可能被jvm内联。

1、热点代码。 如果一个方法的执行频率很高就表示优化的潜在价值就越大。那代码执行多少次才能确定为热点代码?这是根据编译器的编译模式来决定的。如果是客户端编译模式则次数是1500,服务端编译模式是10000。次数的大小可以通过-XX:CompileThreshold来调整。

2、方法体不能太大。jvm中被内联的方法会编译成机器码放在code cache中。如果方法体太大,则能缓存热点方法就少,反而会影响性能。

3、如果希望方法被内联,尽量用private、static、final修饰,这样jvm可以直接内联。如果是public、protected修饰方法jvm则需要进行类型判断,因为这些方法可以被子类继承和覆盖,jvm需要判断内联究竟内联是父类还是其中某个子类的方法。

所以了解jvm方法内联机制之后,会有助于我们工作中写出能让jvm更容易优化的代码,有助于提升程序的性能。

jvm之方法内联优化的更多相关文章

  1. 深入理解java虚拟机(十四)正确利用 JVM 的方法内联

    在IntelliJ IDEA里面Ctrl+Alt+M用来拆分方法.选中一段代码,敲下这个组合,非常简单.Eclipse也用类似的快捷键,使用 Alt+Shift+M.我讨厌长的方法,提起这个下面这个方 ...

  2. Java 方法内联

    什么是Java 方法内联? 我们先来看看普遍的内联函数含义.在维基百科中解释为: 内联函数:在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函 ...

  3. Java方法内联

    一.概念 方法内联就是把调用方函数代码"复制"到调用方函数中,减少因函数调用开销的技术   函数调用过程 1.首先会有个执行栈,存储它们的局部变量.方法名.动态连接 2.当一个方法 ...

  4. JVM 学习(二)Java 内存模型、方法内联、逃逸 --- 2019年4月

    1.Java 的内存模型 定义了 happens-before,如果同一个线程中,字节码的先后顺序,后者观测了前者的运行结果,那么就会按顺序执行. Java 线程之间的通信由 Java 内存模型控制. ...

  5. C#效率优化(2)-- 方法内联

    一.JIT编译器可以通过将方法内联展开(Method Inline Expansion)来提升效率,类似C++中的内联函数(Inline Function),与C++的内联函数不同的是,C#并不支持内 ...

  6. Java中的方法内联

    Java中的方法内联 1. 什么是方法内联 例如有下面的原始代码: static class B { int value; final int get() { return value; } } pu ...

  7. 一个关于内联优化和调用约定的Bug

    很久没有更新博客了(博客园怎么还不更新后台),前几天在写一个Linux 0.11的实验 [1] 时遇到了一个奇葩的Bug,就在这简单记录一下调试过程吧. 现象 这个实验要求在Linux 0.11中实现 ...

  8. Go 中的内联优化

    文讨论 Go 编译器是如何实现内联的以及这种优化方法如何影响你的 Go 代码. 请注意:本文重点讨论 gc,实际上是 golang.org 的 Go 编译器.讨论到的概念可以广泛用于其他 Go 编译器 ...

  9. 修改html内联样式的方法

    问题:如下图弹出页面操作不了 分析:审查元素,发现是内联元素样式z-index:19891015导致的,修改内联元素样式z-index:0发现可以操作了 解决方法:内联样式优先级高,再引入css覆盖样 ...

随机推荐

  1. Linux平台下SSD的TRIM指令的最佳使用方式(不区别对待NVMe)

    SSD写数据会出现什么问题 SSD读写的单位不是位,而是一个块.如果要改变这个块中的一位,首先要将整个块擦写成1,然后再写入更新的数据. 为了解决擦写块的低效,SSD的策略是将需要改写的块,读取出来, ...

  2. 为什么不应该使用goroutine id?

    Goroutine id 的获取方式 之前做的项目中,会使用 goroutine-id(以下简称 goid) 作为日志中的一个标识参数.而 goroutine 的相关信息是不对外暴露的.想要获取 go ...

  3. laravel 数据分页简单示例

    控制器代码:只需用paginate($pageSize)方法查询数据即可 $pageSize:每页显示的记录数 public function index() { $data = Member::pa ...

  4. Java 添加、删除、替换、格式化Word中的文本(基于Spire.Cloud.SDK for Java)

    Spire.Cloud.SDK for Java提供了TextRangesApi接口可通过addTextRange()添加文本.deleteTextRange()删除文本.updateTextRang ...

  5. pycharm 退出虚拟环境

    pycharm 内置虚拟环境 venv 如果要退出就直接 deactivate 命令就行 运行的话直接在命令行输python3  文件名

  6. 你一个 F12 能秒我?

    参考文章 思路决定成败:F12给了我黑色的眼睛我却用它来挖洞 前言 了解大佬的思路才知道自己现在学的到底有多浅. 还没有到点,我就已经进入状态了,生而为人,我很抱歉. F12 的骚操作 Element ...

  7. Python raw_input() 函数

    python raw_input() 用来获取控制台的输入.高佣联盟 www.cgewang.com raw_input() 将所有输入作为字符串看待,返回字符串类型. 注意:input() 和 ra ...

  8. PHP strptime() 函数

    ------------恢复内容开始------------ 实例 解析由 strftime() 生成的时间/日期: <?php$format="%d/%m/%Y %H:%M:%S&q ...

  9. idea修改module name后重启失效

    技术交流群 : 816227112 idea每次修改module name后重启,module还是会在后面加上原来的name. 这时修改: .idea下的modules.xml 内的module名即可 ...

  10. HTTP Request Method(十五种)

    序号 方法 描述 1 GET 请求指定的页面信息,并返回实体主体. 2 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 3 POST 向指定资源提交数据进行处理请求(例如提 ...