首先看看Chat GPT关对于在jvm中,堆是分配对象内存存储的唯一选择吗
的回答
<aside> 🗨️ 在Java虚拟机(JVM)中,堆是主要用于分配对象内存的区域,但并不是唯一的选择。除了堆,Java中还存在栈(Stack)和方法区(Method Area,或元空间Metaspace)等内存区域。
new
关键字创建的对象在堆上进行分配。堆的优势在于它提供了动态内存分配和垃圾回收机制,使得对象的生命周期可以比较灵活。所以,尽管堆是分配对象内存的主要区域,但在Java中有其他内存区域用于不同的目的。选择使用堆还是其他内存区域取决于数据的生命周期、访问模式以及性能需求。
</aside>
其中在栈存储的局部变量和方法调用。基本数据类型和对象引用标识需要jvm做一个筛选,这个筛选方法就叫逃逸分析(Escape Analysis)
在《深入理解Java虚拟机》中关于Java堆内存有这样一段描述: 随着JIT编译期的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。
在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。
但是,有一种特殊情况,那就是如果经过逃逸分析(Escape Analysis)后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,随着方法执行的结束,栈空间就被移除了,也无须进行垃圾回收了。这也是最常见的堆外存储技术。
在JDK 6u23版本之后,Hotspot中默认就已经开启了逃逸分析。如果使用的是较早的版本,开发人员则可以通过:
- 选项
-XX: +DoEscapeAnalysis
显式开启逃逸分析- 通过选项
-XX: +PrintEscapeAnalysis
打印逃逸分析日志,查看逃逸分析的筛选结果。
如何快速判读是否发生了逃逸分析,就看new的对象实体是否有可能在方法外被调用