一、概念
方法内联就是把调用方函数代码"复制"到调用方函数中,减少因函数调用开销的技术
 
函数调用过程
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. 【LeetCode】219. Contains Duplicate II 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 使用set 使用字典 日期 题目地址:https:/ ...

  2. 【LeetCode】73. Set Matrix Zeroes 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 原地操作 新建数组 队列 日期 题目地址:https ...

  3. 【LeetCode】377. Combination Sum IV 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  4. 【剑指Offer】数值的整数次方 解题报告(Python)

    [剑指Offer]数值的整数次方 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://www.nowcoder.com/ta/coding-interviews ...

  5. 编写Java程序,实现对兵营类的封装,将兵营类中的所有属性设置为私有访问权限,方法设置为公有访问权限

    返回本章节 返回作业目录 需求说明: 实现对兵营类的封装 将兵营类中的所有属性设置为私有访问权限. 将兵营类中所有属性的赋值方法设置为公有访问权限. 要求兵营名称的长度在4-8位之间. 要求兵营士兵的 ...

  6. SpringBootAdmin-使用踩坑

    一.版本选择 目前项目中使用的springcloud版本为 Hoxton.SR3,使用的spring-cloud-alibaba版本为2.2.1.RELEASE, 使用的springboot版本为2. ...

  7. centos7 配置登录前和登录信息内容

    登录之前提示信息: 登录之后提示信息: 上述中,只需修改对应的文件即可. 登录之前: vi /etc/issue 登录之后: vi /etc/motd 补充:将文件内容清空的方法,不是删除. 在前面文 ...

  8. vue中使用两个window.onresize问题解决

    在vue开发中,因为引用的父组件和子组件都使用了window.onresize以至于一个window.onresize失效.找了下解决方案,可以采用下面的方式写就可以了. window.onresiz ...

  9. 服务性能监控之Micrometer详解

    Micrometer 为基于 JVM 的应用程序的性能监测数据收集提供了一个通用的 API,支持多种度量指标类型,这些指标可以用于观察.警报以及对应用程序当前状态做出响应. 通过添加如下依赖可以将 M ...

  10. 07.python函数作用域global、nonlocal、LEGB

    函数作用域 作用域 一个标识符的课件范围,这就是标识符的作用域,一般常说的是变量的作用域 def foo():    x = 100 print(x) # 可以访问到吗 上例中x不可以访问到,会抛出异 ...