当前位置: 首页 > news >正文

JVM 逃逸分析

JVM逃逸分析:让Java对象"乖乖听话"的侦探游戏

大家好!我是你们的老朋友"代码神探福尔摩斯",今天要带大家破解一个JVM界的经典悬案——如何让Java对象乖乖待在它该待的地方?

第一章:案发现场——堆与栈的爱恨情仇

(拿出放大镜)先来勘察案发现场。想象我们的内存世界有两个重要区域:

  • 堆区:像个大型公共停车场,所有对象都能自由出入(但停车费高昂)
  • 栈区:像私家车库,只能停放当前线程的私人物品(免费且存取超快)

传统情况下,所有新对象都会被默认停放在堆区停车场。但我们的探案目标是——找到那些可以偷偷溜进私家车库的对象!

public class ParkingLot {// 这个对象必定停在堆区停车场Object publicCar = new Object();void parkCar() {// 这个对象有机会停在栈区车库Object privateCar = new Object();}
}

第二章:逃犯画像——什么对象会"越狱"?

逃逸分析就是JVM的监控系统,专门侦测对象是否会:

  1. 方法逃逸(Method Escape):对象被其他方法引用
  2. 线程逃逸(Thread Escape):对象被其他线程访问

(掏出嫌疑人画像)比如这个"逃犯对象":

public Object createEscapedCar() {Object car = new Object();return car; // 对象逃出方法!
}

而下面这位是"良民对象":

public void createGoodCar() {Object car = new Object();car.drive(); // 对象始终在方法内
}

第三章:特工装备——三种秘密武器

一旦确认对象不会逃逸,JVM特工就会掏出三件法宝:

1. 栈上分配(Stack Allocation)

把对象直接存放在栈帧里,就像把外卖放在家门口的临时寄存架:

void eatNoodles() {// 这个碗不会逃出方法Bowl bowl = new Bowl();bowl.add(new Noodles());bowl.eat();
} // 吃完碗直接收走,无需垃圾回收
2. 标量替换(Scalar Replacement)

把对象拆成零件,就像把自行车拆成车架+轮子:

void rideBike() {Bike bike = new Bike(); // 被拆解为int frame = 1;          // 车架int wheel = 2;          // 轮子System.out.println(frame + wheel);
}
3. 同步消除(Sync Elimination)

发现没人偷车,直接拆掉车锁:

void safeMethod() {Object lock = new Object();synchronized(lock) { // 这个锁会被移除!System.out.println("根本没人抢这个锁");}
}

第四章:实战训练——成为逃逸分析大师

案例1:不会逃逸的乖宝宝
public class GoodBoy {public static void main(String[] args) {for (int i = 0; i < 1000000; i++) {// 这个对象只在循环内使用LocalObject obj = new LocalObject();obj.print();}}static class LocalObject {void print() {System.out.println("我是乖宝宝");}}
}

这个案例中,JVM会进行:

  • 栈上分配(循环内快速创建销毁)
  • 标量替换(可能直接使用基本类型)
案例2:到处乱跑的熊孩子
public class NaughtyKid {private static Object escapedObj;public static void main(String[] args) {for (int i = 0; i < 1000000; i++) {Object obj = new Object();escapedObj = obj; // 对象逃逸到类变量!use(obj);}}static void use(Object obj) {System.out.println(System.identityHashCode(obj));}
}

这个熊孩子对象会:

  • 强制在堆中分配
  • 需要垃圾回收
  • 无法进行任何优化

第五章:侦探手册——优化秘籍

  1. 缩小作用域:尽量让对象在最小范围内活动
  2. 避免暴露引用:谨慎使用返回值、类变量、集合类
  3. 警惕内部类:匿名内部类会隐式持有外部类引用
  4. 慎用同步块:能用局部锁就不用实例锁
  5. 优先使用局部变量:方法内的临时变量最安全

第六章:结案报告——注意事项

虽然逃逸分析很强大,但要注意:

  • 不是所有JVM实现都支持(但主流JDK都支持)
  • 分析需要消耗CPU资源
  • 对于复杂代码可能分析失败
  • 可以使用-XX:+DoEscapeAnalysis开启(默认开启)
  • 使用-XX:+PrintEscapeAnalysis查看分析结果

(摘下侦探帽)现在你已经成为逃逸分析专家了!记住:每个对象都有自己最适合的"家",我们的任务就是帮它们找到最合适的归宿。下次写代码时,不妨多想想:“这个对象会逃逸吗?” 保准你的代码性能更上一层楼!

相关文章:

  • 第十课认识约数
  • Go多服务项目结构优化:为何每个服务单独设置internal目录?
  • 猿人学第十七题—天杀的http2.0
  • 在 Vue 3 中实现刮刮乐抽奖
  • 牛客练习赛138
  • PTA:jmu-ds-拓扑排序
  • JDBC链接数据库
  • 程序代码篇---Python视频流
  • OrangePi Zero 3学习笔记(Android篇)5 - usbutils编译(更新lsusb)
  • DVWA靶场Cryptography模块medium不看原码做法
  • kubectl top 查询pod连接数
  • Go基于plugin的热更新初体验
  • 【赵渝强老师】TiDB SQL层的工作机制
  • 数据分析2
  • 物联网、数字化工厂与智能智慧技术未来发展方向
  • 光的本质(以暗物质维度粒子为介质的能量传导)
  • Kubernetes应用发布方式完整流程指南
  • Java代理
  • ERP学习(二):用友软件产品之系统管理
  • 网络原理(Java)
  • 云南省安委会办公室:大理州安全生产形势比较严峻,事故总量一直居高不下
  • 李在明正式登记参选下届韩国总统
  • 万达电影:股东杭州臻希拟减持不超1.3927%公司股份
  • 欧派家居:一季度营收降4.8%,目前海外业务整体体量仍较小
  • 中国驻美国大使馆发言人就中美经贸高层会谈答记者问
  • 明查|这是“C919迫降在农田”?实为飞机模型将用于科普体验