一、概念
方法内联就是把调用方函数代码"复制"到调用方函数中,减少因函数调用开销的技术
 
函数调用过程
1、首先会有个执行栈,存储它们的局部变量、方法名、动态连接
2、当一个方法被调用,一个新的栈帧会被加到栈顶,分配的本地变量和参数会存储在这个栈帧
3、跳转到目标方法代码执行
4、方法返回的时候,本地方法和参数被销毁,栈顶被移除
5、返回原来的地址执行
 
注:这就是通常说的函数调用的压栈和出栈过程,因此,函数调用需要有一定的时间开销和空间开销,当一个方法体不大,但又频繁被调用时,这个时间和空间开销会相对变得很大,变得非常不划算,同时降低了程序的性能。根据二八原则,80%的性能消耗其实是发生在20%的代码上,对热点代码的针对性优化可以提升整体系统的性能
 
二、方法内联的原理
就如上面所说,就是把调用方函数代码"复制"到调用方函数中
 
看如下例子:
private int add2(int x1 , int x2 , int x3 , int x4) {
return add1(x1 , x2) + add1(x3,x4);
} private int add1(int x1 , int x2) {
return x1 + x2;
}

  

 
运行一段时间后,代码被内联翻译成:
private int add2(int x1 , int x2 , int x3 , int x4) {
//return add1(x1 , x2) + add1(x3,x4);
return x1 + x2 + x3 + x4;
}
 
三、方法内联的条件
JVM会自动的识别热点方法,并对它们使用方法内联优化。那么一段代码需要执行多少次才会触发JIT优化呢?通常这个值由-XX:CompileThreshold参数进行设置:
  使用client编译器时,默认为1500;
    使用server编译器时,默认为10000;
但是一个方法就算被JVM标注成为热点方法,JVM仍然不一定会对它做方法内联优化。其中有个比较常见的原因就是这个方法体太大了,分为两种情况。
   如果方法是经常执行的,默认情况下,方法大小小于325字节的都会进行内联(可以通过** -XX:MaxFreqInlineSize=N**来设置这个大小)
       如果方法不是经常执行的,默认情况下,方法大小小于35字节才会进行内联(可以通过** -XX:MaxInlineSize=N **来设置这个大小)
 
我们可以通过增加这个大小,以便更多的方法可以进行内联;但是除非能够显著提升性能,否则不推荐修改这个参数。因为更大的方法体会导致代码内存占用更多,更少的热点方法会被缓存,最终的效果不一定好。
 
JVM参数:(-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining)
当我们执行1000次
 

当我们执行10001次

 
四、内联的隐藏条件
 
虽然JIT号称可以针对代码全局的运行情况而优化,但是JIT对一个方法内联之后,还是可能因为方法被继承,导致需要类型检查而没有达到性能的效果
想要对热点的方法使用上内联的优化方法,最好尽量使用final、private、static这些修饰符修饰方法,避免方法因为继承,导致需要额外的类型检查,而出现效果不好情况。
 
五、结论
 
1、针对热点方法,想要通过JIT内联优化来提升性能的建议 
2、更小的方法体,JVM总是偏好更小的方法。
3、尽量使用final、private、static修饰符
4、使用+PrintInlining参数校验效果(【PrintInlining】-XX:+UnlockDiagnosticVMOptions必须配合参数{2}使用,并且只能加在其后才能生效)

Java方法内联的更多相关文章

  1. Java 方法内联

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

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

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

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

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

  4. Java中的方法内联

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

  5. jvm之方法内联优化

    前言 在日常中工作中,我们时不时会代码进行一些优化,比如用新的算法,简化计算逻辑,减少计算量等.对于java程序来说,除了开发者本身对代码优化之外,还有一个"人"也在背后默默的优化 ...

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

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

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

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

  8. C++ 内联(inline)函数

    目录 内联函数的使用方法 内联函数的使用规则 使用inline的时机 inline函数与宏函数的差异 inline是C++关键字,在函数声明或定义中,函数返回类型前加上关键字inline,即可以把函数 ...

  9. C#内联函数 特性 MethodImplOptions.AggressiveInlining)

    [MethodImpl(MethodImplOptions.AggressiveInlining)] 内联函数 Impl:implement的缩写 内联函数 在计算机科学中,内联函数(有时称作在线函数 ...

随机推荐

  1. 1369 - Answering Queries

    1369 - Answering Queries    PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 ...

  2. 剖析Defi之Uinswap_0

    Uniswap是什么,不需要讲了吧.YYDS(永远嘀神) 介绍几个概念: 恒定乘积算法:可以简单看作X * Y = K,这里K(乘积)保持不变,所以叫恒定乘积算法,该函数是一个反曲线. 自动流动性协议 ...

  3. ret2dl_resolve

    ret2dl_resolve是一种比较复杂的高级ROP技巧,利用它之前需要先了解动态链接的基本过程以及ELF文件中动态链接相关的结构. 我根据raycp师傅的文章,动手调试了一下: https://r ...

  4. 编写Java程序,在维护英雄数据的业务过程中复用数据库操作封装类

    返回本章节 返回作业目录 需求说明: 继续完善英雄信息系统,将HeroAccess类中数据库连接相关代码独立出来,并将其封闭成数据库操作工具类DbConnection,便于管理和代码复用. 在Hero ...

  5. C#读取注释的方法

    友好的注释能提高代码的可读性,几乎所有的编程语言都支持注释. 在C#中,注释不是可执行代码的一部分,因此注释不会被编译到程序集中去,但是我们可以提取注释[右键项目]-[属性]-[生成]-[输出]-[X ...

  6. C# 绘制印章

    最近有个.net core的项目要绘制印章功能,一个公司印章,一个个人印章,于是抽了点时间自己写了一个,现在分享出来 using System; using System.Collections.Ge ...

  7. Ubuntu18.04安装/卸载NVIDIA显卡驱动

    1 显卡驱动下载 官网:NVIDIA 搜索适合本机的驱动 获取最新版本驱动 立即下载 文件 以上,显卡驱动下载完成. 2 显卡驱动安装 2.1 添加可执行权限 进入驱动文件目录sudo chmod a ...

  8. Ubuntu18.04升级内核后修改grub文件启动顺序

    采坑:之前线上的服务器内核是4.15.0,后面有的服务跑不起来,说是要升级内核,于是就升级了,然后改了/etc/default/grub的启动顺序,改错了就启动不起来了,哈哈.后面多次尝试还是改成功了 ...

  9. java运算符2

    续: 位运算符(<<,>>,>>>) 1.<<: 3<<2,二进制左移2位,右边用0补齐       3的二进制:00000000 0 ...

  10. 我踩过的Django的坑

    把自己在使用Django过程中吃过的亏 踩过的坑 记录一下 1. unique_together传的是元组 正确:unique_together = (('app_id', 'module_id', ...