java逃逸分析

Java中的逃逸分析 逃逸分析是一种在Java编译器和运行时环境中进行的优化技术,用于确定对象的生命周期是否会逃逸出方法或线程的范围。对于不逃逸的对象,编译器可以进行一些优化,例如在栈上分配内存而不是堆上分配,或者通过标量替换将对象拆分为多个独立的字段。这些优化可以显著提高程序的性能和内存利用率。总之,逃逸分析是Java编译器和运行时环境中的一种优化技术,用于确定对象的生命周期是否会逃逸出方法或线程的范围。在上面的例子中,通过在新线程中创建Point对象,并将其赋值给静态变量point,使得该对象逃逸出新线程的范围。 阅读详情

@author StormMa
@date 2017-03-09


生命不息,奋斗不止!

概念引入

我们都知道,Java 创建的对象都是被分配到堆内存上,但是事实并不是这么绝对,通过对Java对象分配的过程分析,可以知道有两个地方会导致Java中创建出来的对象并一定分别在所认为的堆上。这两个点分别是Java中的逃逸分析和TLAB(Thread Local Allocation Buffer)线程私有的缓存区。

基本概念介绍

逃逸分析,是一种可以有效减少Java程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。
在计算机语言编译器优化原理中,逃逸分析是指分析指针动态范围的方法,它同编译器优化原理的指针分析和外形分析相关联。当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。通俗点讲,如果一个对象的指针被多个方法或者线程引用时,那么我们就称这个对象的指针发生了逃逸。
Java在Java SE 6u23以及以后的版本中支持并默认开启了逃逸分析的选项。Java的 HotSpot JIT编译器,能够在方法重载或者动态加载代码的时候对代码进行逃逸分析,同时Java对象在堆上分配和内置线程的特点使得逃逸分析成Java的重要功能。

代码示例
package me.stormma.gc;

/**
 * <p>Created on 2017/4/21.</p>
 *
 * @author stormma
 *
 * @title <p>逃逸分析</p>
 */
public class EscapeAnalysis {

    public static B b;

    /**
     * <p>全局变量赋值发生指针逃逸</p>
     */
    public void globalVariablePointerEscape() {
        b = new B();
    }

    /**
     * <p>方法返回引用,发生指针逃逸</p>
     * @return
     */
    public B methodPointerEscape() {
        return new B();
    }

    /**
     * <p>实例引用发生指针逃逸</p>
     */
    public void instancePassPointerEscape() {
        methodPointerEscape().printClassName(this);
    }

    class B {
        public void printClassName(EscapeAnalysis clazz) {
            System.out.println(clazz.getClass().getName());
        }
    }
}

逃逸分析研究对于 java 编译器有什么好处呢?我们知道 java 对象总是在堆中被分配的,因此 java 对象的创建和回收对系统的开销是很大的。java 语言被批评的一个地方,也是认为 java 性能慢的一个原因就是 java不支持栈上分配对象。JDK6里的 Swing内存和性能消耗的瓶颈就是由于 GC 来遍历引用树并回收内存的,如果对象的数目比较多,将给 GC 带来较大的压力,也间接得影响了性能。减少临时对象在堆内分配的数量,无疑是最有效的优化方法。java 中应用里普遍存在一种场景,一般是在方法体内,声明了一个局部变量,并且该变量在方法执行生命周期内未发生逃逸,按照 JVM内存分配机制,首先会在堆内存上创建类的实例(对象),然后将此对象的引用压入调用栈,继续执行,这是 JVM优化前的方式。当然,我们可以采用逃逸分析对 JVM 进行优化。即针对栈的重新分配方式,首先我们需要分析并且找到未逃逸的变量,将该变量类的实例化内存直接在栈里分配,无需进入堆,分配完成之后,继续调用栈内执行,最后线程执行结束,栈空间被回收,局部变量对象也被回收,通过这种方式的优化,与优化前的方案主要区别在于对象的存储介质,优化前是在堆中,而优化后的是在栈中,从而减少了堆中临时对象的分配(较耗时),从而优化性能。

使用逃逸分析进行性能优化(-XX:+DoEscapeAnalysis开启逃逸分析)


public void method() {

    Test test = new Test();

    //处理逻辑

    ......

    test = null;
}

这段代码,之所以可以在栈上进行内存分配,是因为没有发生指针逃逸,即是引用没有暴露出这个方法体。

栈和堆内存分配比较
package me.stormma.gc;

/**
 * <p>Created on 2017/4/21.</p>
 *
 * @author stormma
 * @description: <p>内存分配比较</p>
 */
public class EscapeAnalysisTest {

    public static void alloc() {
        byte[] b = new byte[2];
        b[0] = 1;
    }

    public static void main(String[] args) {
        long b = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            alloc();
        }
        long e = System.currentTimeMillis();
        System.out.println(e - b);
    }

}

JVM 参数为-server -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:+PrintGC, 运行结果

这里写图片描述

JVM 参数为-server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGC, 运行结果

这里写图片描述

性能测试
package me.stormma.gc;

/**
 * <p>Created on 2017/4/21.</p>
 *
 * @author stormma
 * 
 * @description: <p>利用逃逸分析进行性能优化</p>
 */
public class EscapeAnalysisTest {

    private static class Foo {

        private int x;

        private static int counter;



        public Foo() {

            x = (++counter);

        }

    }



    public static void main(String[] args) {

        long start = System.nanoTime();

        for (int i = 0; i < 1000 * 1000 * 10; ++i) {

            Foo foo = new Foo();

        }

        long end = System.nanoTime();

        System.out.println("Time cost is " + (end - start));

    }

}

使用逃逸分析优化 JVM输出结果( -server -XX:+DoEscapeAnalysis -XX:+PrintGC)

Time cost is 11012345

未使用逃逸分析优化 JVM 输出结果( -server -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:+PrintGC)

[GC (Allocation Failure)  33280K->408K(125952K), 0.0010344 secs]
[GC (Allocation Failure)  33688K->424K(125952K), 0.0009799 secs]
[GC (Allocation Failure)  33704K->376K(125952K), 0.0007297 secs]
[GC (Allocation Failure)  33656K->456K(159232K), 0.0014817 secs]
Time cost is 68562263

分析结果,性能优化1/6

逻辑电平(TTL/CMOS/LVDS/LVPECL/CML) 逻辑电平介绍 TTL------晶体管-晶体管逻辑门(Transistor-Transistor Logic gate) TTL采用5V电源 阅读详情

相关推荐

固件测试工具选型需要考察的功能点汇总

通过专业的固件测试工具可以帮助我们提高测试效率、提升测试的覆盖度、确保测试的准确性,保障产品的安全和质量。本文我们讲固件测试工具的功能点进行梳理和汇总,方便大家在采购固件测试工具时进行选型比对。

daopuyun的博客 2112

Java - 深入理解Java中的逃逸分析

在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件。第二段编译是把.class转换成机器指令的过程。第一段编译就是​​javac​​命令。在第二编译阶段,JVM 通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解释翻译。很显然,经过解释执行,其执行速度必然会比可执行的二进制字节码程序慢很多。这就是传统的JVM的解释器(Interpreter)的功能。为了解决这种效率问题,引入了技术。

ch568的博客 3249

Java对象逃逸分析

Java对象逃逸分析

Deronn的博客 2106

用 Python 和 uiautomation 实现微信批量发送

思路是这样,将要发送的人员名单(包括称呼)以及发送内容都维护到Excel里,程序运行时读取Excel里内容,自动搜索人员姓名(微信昵称或备注名),填入要发送的内容,拼接上称呼(如果需要的话)自动点击发送,这样轮巡直至名单人员全部发送完成。、

jankingdom的专栏 1471

X电容与Y电容,看这一篇就够了

本文详细介绍了X电容与Y电容的定义、作用、位置、分类,以及它们在实际应用中的容值选取和计算方法。通过汽车电子应用和X电容放电电路的实例,帮助读者深入理解这两种安规电容的重要性。文章还探讨了电容放电电阻的计算,确保符合安全规范。

让你爱上电路设计 7020

Java对象逃逸及逃逸分析

随着 JIT 编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。但是,有一种特殊情况,那就是如果经过逃逸分析(Escape Analysis)后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,也无须进行垃圾回收了。这也是最常见的堆外存储技术。

m0_72106802的博客 4074

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的生活垃圾检测与分类系统(Python+PySide6界面+训练代码)

随着城市化进程的加速和人口增长,生活垃圾管理已成为现代城市面临的重要挑战。传统的垃圾处理方法效率低下且成本高昂,急需智能化解决方案。本文详细介绍了基于YOLO系列算法(特别是YOLOv8)的智能生活垃圾检测与分类系统,该系统能够实时识别和分类多种生活垃圾,为智能垃圾处理和回收提供技术支持。系统包含完整的数据集构建、模型训练、评估和可视化界面,并提供了完整的实现代码。

YOLO 117

什么是Java的逃逸分析

综上所述,Java Escape Analysis 是在 Java 程序的编译过程中用来确定哪些对象可以分配到栈上而不是堆上的过程。因为在栈而不是堆上分配对象,那么对象就是封闭在一个线程内,不与其他线程共享,从而在高并发的程序中消除了对象加解锁同步带来的性能消耗。具体来说,Java程序在编译时,编译器会做Escape Analysis,判断哪些对象可以分配到栈上,而不是堆上。为了确定可以在栈上分配哪些对象,编译器将分析程序代码,以查找在方法外部,是否有目标对象的引用。如果没有的话,如下所示,将在栈上分配。

编哥的技术园 453

Darknet-Yolov3 移植过程

本教程面向使用寒武纪平台进行深度学习推理任务的开发者。针对当前主流检测网络darknet-yolov3,进行寒武纪平台的移植。开发者对照移植过程,能够利用寒武纪智能处理器设备完成多种场景的目标检测任务。本实验代码基于 Neuware 1.6.1 与 Python 2.7 环境。

shengyin714959的博客 438

【AI 编程工具】Codex配置部署指南

目录一、环境准备与基础安装1. 系统兼容性检查2. 前置依赖安装3. 安装方式选择二、API密钥配置与认证1. 获取API密钥2. 配置文件设置3. 临时配置方式三、沙盒环境配置与安全策略1. 沙盒模式选择2. 安全最佳实践四、高级功能配置1. 模型上下文协议(MCP)配置2. 模型版本切换3. 自定义网关配置五、常见问题排查1. 安装失败2. API调用失败3. 处理速度慢4. 配置文件不生效六、生产环境部署建议macOS/Linux:官方提供稳定支持,推荐使用原生环境Windows:官方标注为实验性支持

以实战经验介绍行业知识 2895

Java 逃逸分析

Java 逃逸分析 什么是逃逸分析? 关于 Java 逃逸分析的定义: 逃逸分析(Escape Analysis)简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。 逃逸分析的 JVM 参数如下: 开启逃逸分析:-XX:+DoEscapeAnalysis 关闭逃逸分析:-XX:-DoEscapeAnalysis 显示分析结果...

qq_28957407的博客 534

家用智能监控摄像机如何使用NAS进行存储/备份(小米智能摄像机如何解决群晖 / 飞牛 NAS 识别失败、文件目录不显示问题)

小米摄像头NAS存储总出问题?🤯 别慌!本文揭秘NAS底层逻辑,群晖、飞牛实战指南。手把手教你排查解决所有难题,轻松搞定监控录像安全备份!🔒

XiaoqiangClub的博客 2697

Java中对象的逃逸分析

逃逸分析的定义 对象的逃逸状态 1. 全局逃逸 2. 参数逃逸 3. 没有逃逸 小结 逃逸分析优化方式 1. 锁消除 2. 栈上分配 3. 标量替换

骑个小蜗牛的博客 9579

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

java 逃逸分析_面试中遇到的java逃逸分析问题

前言记得几年前有一次栈长去面试,问到了这么一个问题:Java中的对象都是在堆中分配吗?说明为什么!当时我被问得一脸蒙逼,瞬间被秒杀得体无完肤,当时我压根就不知道他在考什么知识点,难道对象不是在堆中分配吗?最后就没然后了,回去等通知了。。下面我收集了一下网友的回答。回答很精彩,大家可以加入一起搞技术,我现在将答案总结一下给大家。什么是逃逸分析?关于 Java 逃逸分析的定义:逃逸分析(Escape ...

weixin_39573781的博客 123

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

java 逃逸分析_java中的逃逸分析

逃逸分析public static StringBuffer craeteStringBuffer(String s1, String s2) {StringBuffer sb = new StringBuffer();sb.append(s1);sb.append(s2);return sb;}public static String createStringBuffer(String s1, ...

weixin_39526706的博客 167

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

java 逃逸分析_JVM之逃逸分析

什么是逃逸分析在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法——分析在程序的哪些地方可以访问到指针。它涉及到指针分析和形状分析。当一个变量(或对象)在子程序中被分配时,一个指向变量的指针可能逃逸到其它执行线程中,或是返回到调用者子程序。如果使用尾递归优化(通常在函数编程语言中是需要的),对象也可以看作逃逸到被调用的子程序中。如果一种语言支持第一类型的延续性在Scheme和Standar...

weixin_30878135的博客 483

Java内存对象的逃逸分析

逃逸分析英文作Escape Analysis。在计算机语言编译器优化原理中,逃逸分析是指分析指针动态范围的方法,它同编译器优化原理的指针分析和外形分析相关联。 当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。 在Java中比如下面的方法: ...... static V global_

ustcxjt的专栏 1357

Java逃逸分析理解

在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件。第二段编译是把.class转换成机器指令的过程。 第一段编译就是javac命令。 在第二编译阶段,JVM 通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解释翻译。很显然,经过解释执行,其执行速度必然会比可执行的二进制字节码程序慢很多。这就是传统的JVM的解释器(Interpreter)的功能。为了解决这种效率问题,引入了 JIT(即时编译)...

百木成林 205

java1.7 内存 逃逸分析_Java逃逸分析详解及代码示例

概念引入我们都知道,Java 创建的对象都是被分配到堆内存上,但是事实并不是这么绝对,通过对Java对象分配的过程分析,可以知道有两个地方会导致Java中创建出来的对象并一定分别在所认为的堆上。这两个点分别是Java中的逃逸分析和TLAB(Thread Local Allocation Buffer)线程私有的缓存区。基本概念介绍逃逸分析,是一种可以有效减少Java程序中同步负载和内存堆分配压力的...

weixin_39752215的博客 422

关于Java 逃逸分析

什么是逃逸分析? 关于 Java 逃逸分析的定义: 逃逸分析(Escape Analysis)简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。 逃逸分析的 JVM 参数如下: 开启逃逸分析:-XX:+DoEscapeAnalysis 关闭逃逸分析:-XX:-DoEscapeAnalysis 显示分析结果:-XX:+Prin...

weixin_43895008的博客 327
上一篇: web请求响应规范化处理
下一篇: 微信JSAPI支付教程
一北
博客等级 码龄11年 195粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值