Java对象逃逸
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。
未经允许不得转载
目录
- 一、导读
- 二、概览
- 三、相关知识
- 3.1 逃逸分析
- 3.2 对象逃逸状态
- 3.3 Java中的对象都是在堆中分配吗?说明为什么!
- 四、 推荐阅读

一、导读
我们继续总结学习Java基础知识,温故知新。
逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中,称为方法逃逸。
二、概览
Java对象逃逸指的是一个对象在其应该被限制访问的范围之外被引用或访问的情况,简单解释就是我有一个方法,在方法内创建了一个对象,但是这个对象传递到其他地方了。
在Java中,对象一般在包含它们的方法中创建和使用,当方法结束时,这些对象会被回收。然而,当对象在方法中被引用或传递到其他方法中时,就会发生对象逃逸。
我们举例
这种写法直接返回的是对象,用处就是被别的变量所引用,会造成对象逃逸,从而增加了GC的压力。public StringBuilder getSb(){StringBuilder sb = new StringBuilder("");return sb;}不如改成下面这样public String getSb1(){StringBuilder sb = new StringBuilder("");return sb.toString();}
第一段代码中的sb就逃逸了,而第二段代码中的sb就没有逃逸。
三、相关知识
在这之前,我们要先了解一些jvm的基本知识。

Java运行时数据区(Runtime Data Area)是指在Java程序执行期间,Java虚拟机所管理的诸多内存区域(分别用于存储不同的数据),如上图所示,包含了以下几个部分:
- 堆区 (主要用于存储对象实例、数组)
- 栈区 (主要存放java方法、局部变量、操作数栈、动态链接、方法出口、基本类型的变量数据、对象的引用等)
- 方法区 (主要用于存储类型信息、常量、静态变量、即时编译代码等)
- 程序计数器
一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,
第一段是把.java文件转换成.class文件。
第二段是把.class转换成机器指令的过程,JVM 通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解释翻译,后来为了解决效率问题,引入了 JIT(即时编译) 技术。
JIT会对代码做很多优化。其中有一部分优化的目的就是减少内存堆分配压力,其中一种重要的技术叫做逃逸分析。通过逃逸分析,Java Hotspot编译器能够
分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。逃逸分析的基本行为就是分析对象动态作用域
public static StringBuffer craeteStringBuffer(String s1, String s2) {StringBuffer sb = new StringBuffer();sb.append(s1);sb.append(s2);return sb;
}sb是一个方法内部变量,上述代码中直接将sb返回,这样这个sb 有可能被其他方法所改变,这样它的作用域就不只是在方法内部
3.1 逃逸分析
逃逸分析(Escape Analysis)简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。
在Java代码运行时,通过JVM参数可指定是否开启逃逸分析,
- -XX:+DoEscapeAnalysis : 开启逃逸分析. 从jdk 1.7开始已经默认开始逃逸分析
- -XX:-DoEscapeAnalysis : 关闭逃逸分析 。
- -XX:+PrintEscapeAnalysis : 显示分析结果
使用逃逸分析,编译器可以对代码做如下优化:
- 同步省略 (锁消除)
public void f() {Object hollis = new Object();synchronized(hollis) {System.out.println(hollis);}
}优化后变成
public void f() {Object hollis = new Object();System.out.println(hollis);
}
- 分离对象或标量替换
- 将堆分配转化为栈分配
当对象没有发生逃逸时,要使指向该对象的指针永远不会逃逸,对象可能是栈分配的候选,而不是堆分配,该对象就可以通过标量替换分解成成员标量分配在栈内存中,
和方法的生命周期一致,随着栈帧出栈时销毁,减少了 GC 压力,提高了应用程序性能
3.2 对象逃逸状态
1、全局逃逸(GlobalEscape)
即一个对象的作用范围逃出了当前方法或者当前线程,有以下几种场景:
- 对象是一个静态变量
- 对象是一个已经发生逃逸的对象
- 对象作为当前方法的返回值
2、参数逃逸(ArgEscape)
即一个对象被作为方法参数传递或者被参数引用,但在调用过程中不会发生全局逃逸,这个状态是通过被调方法的字节码确定的。
对象逃逸可能会导致以下问题:
- 安全问题:对象逃逸可以使对象暴露给不受信任的代码,可能导致数据泄露或被篡改。
- 性能问题:对象逃逸可能导致对象的生命周期变得不可预测,增加垃圾回收的负担,降低系统性能。
- 并发问题:对象逃逸可能导致多个线程同时访问同一个对象,造成线程安全问题。
为了解决对象逃逸问题,可以采取以下措施:
- 限制对象的访问范围:将对象的作用域限制在方法内部,避免在方法外部引用或传递对象。
- 使用局部变量代替成员变量:将对象定义为方法内的局部变量而不是成员变量,这样可以避免对象在方法外部被引用。
- 使用不可变对象:如果对象是不可变的,那么即使发生逃逸,也不会出现安全和并发问题。
- 使用线程安全的数据结构:如果对象需要在多个线程之间共享,应该使用线程安全的数据结构或采用同步控制机制来保证并发安全性。
通过避免对象逃逸,可以提高代码的安全性、性能和并发性能。
3.3 Java中的对象都是在堆中分配吗?说明为什么!
对象和数组并不一定都在堆上分配内存的,随着JIT编译器的发展,在编译期间,如果JIT经过逃逸分析,发现有些对象没有逃逸出方法,
那么有可能堆内存分配会被优化成栈内存分配,
JIT编译器就可以在编译期间根据逃逸分析的结果,来决定是否可以将对象的内存分配从堆转化为栈。
举个栗子:
先定义一个类 XYZclass XYZ {int i;
}在定义一个方法 abc(),方法内使用了XYZ类,但是并没有外部引用,也就说这个对象不会发生逃逸。public void abc() {XYZ xyz = new XYZ();
}最后再定义一个for循环来调用abc()方法,假设我们在代码中创建100万个XYZ对象,for (int i = 0; i < 1000000; i++) {abc();}
假设我们先关闭逃逸分析,在代码结束前使用[jmap][1]命令,来查看下当前堆内存中有100万个XYZ对象.
-Xmx4G -Xms4G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
接下来,我们开启逃逸分析,再来执行下以上代码,使用jmap命令,来查看下当前堆内存中有几万个XYZ对象,不是一个量级。
堆内存中分配的对象数量大量减少,
-Xmx4G -Xms4G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
四、 推荐阅读
Java 专栏
SQL 专栏
数据结构与算法
Android学习专栏
未经允许不得转载

相关文章:
Java对象逃逸
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。 未经允许不得转载 目录 一、导读二、概览三、相关知识3.1 逃逸…...
Greenplum的数据库年龄检查处理
概述 Greenplum是基于Postgresql数据库的分布式数据库,而PG数据库在事务及多版本并发控制的实现方式上很特别,采用的是递增事务id的方法,事务id大的事务,认为比较新,反之事务id小,认为比较旧。 事务id的上…...
[HCIE] IPSec-VPN (IKE自动模式)
概念: IKE:因特网密钥交换 实验目标:pc1与pc2互通 步骤1:R1与R3配置默认路由 R1: ip route-static 0.0.0.0 0.0.0.0 12.1.1.2 R2: ip route-static 0.0.0.0 0.0.0.0 23.1.1.2 步骤2:配ACL…...
Qt/QML编程学习之心得:一个Qt工程的学习笔记(九)
这里是关于如何使用Qt Widget开发,而Qt Quick/QML的开发是另一种方式。 1、.pro文件 加CONFIG += c++11,才可以使用Lamda表达式(一般用于connect的内嵌槽函数) 2、QWidget 这是Qt新增加的一个类,基类,窗口类,QMainWindow和QDialog都继承与它。 3、Main函数 QApplicati…...
c++ 课程笔记
105课: cpp文件分为 .h .cpp .cpp 文件 110课:124课 深拷贝 浅拷贝 自建拷贝构造解决浅拷贝释放new后堆区析构函数的问题 (浅拷贝 拷贝内存地址, 释放堆区时 导致源数据 释放时,该地址无数据?而报错) 浅拷贝: 拷贝了对方的值和 堆区内存地址(删除 影响原数据堆区) 深拷贝…...
ELK企业级日志分析平台——ES集群监控
启用xpack认证 官网:https://www.elastic.co/guide/en/elasticsearch/reference/7.6/configuring-tls.html#node-certificates 在elk1上生成证书 [rootelk1 ~]# cd /usr/share/elasticsearch/[rootelk1 elasticsearch]# bin/elasticsearch-certutil ca[rootelk1 ela…...
Twincat使用:EtherCAT通信扫描硬件设备链接PLC变量
EtherCAT通信采用主从架构,其中一个主站设备负责整个EtherCAT网络的管理和控制,而从站设备则负责在数据环网上传递数据。 主站设备可以是计算机、工控机、PLC等, 而从站设备可以是传感器、执行器、驱动器等。 EL3102:MDP5001_300_CF8D1684;…...
手机APP-MCP走蓝牙无线遥控智能安全帽~执法记录仪~拍照录像,并可做基础的配置,例如修改服务器IP以及配置WiFi等
手机APP-MCP走蓝牙无线遥控智能安全帽~执法记录仪~拍照录像,并可做基础的配置,例如修改服务器IP以及配置WiFi等 手机APP-MCP走蓝牙无线遥控智能安全帽~执法记录仪~拍照录像,并可做基础的配置,例如修改服务器IP以及配置WiFi等, AIoT万物智联,智能安全帽…...
网络互联与IP地址
目录 网络互联概述网络的定义与分类网络的定义网络的分类 OSI模型和DoD模型网络拓扑结构总线型拓扑结构星型拓扑结构环型拓扑结构 传输介质同轴电缆双绞线光纤 介质访问控制方式CSMA/CD令牌 网络设备网卡集线器交换机路由器总结 IP地址A、B、C类IP地址特殊地址形式 子网与子网掩…...
Android设计模式--模板方法模式
一,定义 定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 在面向对象的开发过程中,通常会遇到这样一个问题,我们知道一个算法所需的关键步…...
大语言模型——BERT和GPT的那些事儿
前言 自然语言处理是人工智能的一个分支。在自然语言处理领域,有两个相当著名的大语言模型——BERT和GPT。两个模型是同一年提出的,那一年BERT以不可抵挡之势,让整个人工智能届为之震动。据说当年BERT的影响力是GPT的十倍以上。而现在&#…...
Docker 命令详解
1. 容器生命周期管理 命令说明文档run创建一个新的容器并运行一个命令Docker run 命令start/stop/restart启动、停止、重启容器Docker start/stop/restart 命令kill杀掉一个运行中的容器Docker kill 命令rm删除一个或多个容器Docker rm 命令pause/unpause暂停 恢复容器中所有的…...
ios打包,证书获取
HBuilderX 打包ios界面: Bundle ID(AppID): 又称应用ID,是每一个ios应用的唯一标识,就像一个人的身份证号码; 每开发一个新应用,首先都需要先去创建一个Bundle ID Bundle ID 格式: 一般为&…...
linux(nginx安装配置,tomcat服务命令操作)
首先进系统文件夹 /usr/lib/systemd/systemLs | grep mysql 查看带有命名有MySQL的文件夹修改tomcat.service文件复制jdk目录替换成我们的路径替换成我们的路径进入这个目录,把修改好的文件拖到我们的工具里面重新刷新系统 systemctl daemon-reload查看tomcat状态…...
jQuery_03 dom对象和jQuery对象的互相转换
dom对象和jQuery对象 dom对象 jQuery对象 在一个文件中同时存在两种对象 dom对象: 通过js中的document对象获取的对象 或者创建的对象 jQuery对象: 通过jQuery中的函数获取的对象。 为什么使用dom或jQuery对象呢? 目的是 要使用dom对象的函数或者属性 以及呢 要…...
Mysql 中如何导入数据?
文章目录 前言使用 LOAD DATA 导入数据使用 mysqlimport 导入数据mysqlimport的常用选项介绍后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:Mysql 🐱👓博主在前端领域还有很多知识和技术需要掌握,正…...
深入了解前馈网络、CNN、RNN 和 Hugging Face 的 Transformer 技术!
一、说明 本篇在此对自然语言模型做一个简短总结,从CNN\RNN\变形金刚,和抱脸的变形金刚库说起。 二、基本前馈神经网络: 让我们分解一个基本的前馈神经网络,也称为多层感知器(MLP)。此代码示例将࿱…...
Flink Table API 读写MySQL
Flink Table API 读写 MySQL import org.apache.flink.connector.jdbc.table.JdbcConnectorOptions; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.api.DataTypes; import org.apache.flink.table.api.Envi…...
Nginx 开源版安装
下载 tar.gz安装包,上传。 解压 [rootlocalhost ~]# tar zxvf nginx-1.21.6.tar.gz nginx-1.21.6/ nginx-1.21.6/auto/ nginx-1.21.6/conf/ nginx-1.21.6/contrib/ nginx-1.21.6/src/ ... ...安装gcc [rootlocalhost nginx-1.21.6]# yum install -y gcc 已加载插件…...
『亚马逊云科技产品测评』活动征文|低成本搭建物联网服务器thingsboard
授权声明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 Developer Centre, 知乎,自媒体平台,第三方开发者媒体等亚马逊云科技官方渠道。 0. 环境 - ubuntu22(注意4G内存勉强够,部署完…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
