对象竟然会在栈上分配内存?
![]() 大量资源。 若确定一个对象不会逃逸出线程,那让该对象在栈上分配内存就是个不错主意,对象所占用内存空间就可随栈帧出栈而销毁。 在一般应用中,完全不会逃逸的局部对象和不会逃逸出线程的对象所占比例很大,若能使用栈上分配,则大量对象就会随方法结束而自动销毁,GC系统压力会下降很多。 栈上分配可支持方法逃逸,但不能支持线程逃逸。 2.2 标量替换(Scalar Replacement) 2.2.1 标量 若一个数据已经无法再分解成更小数据,JVM中的原始数据类型(如 int、long 等数值类型及 reference 类型)都不能再进一步分解,这些数据即为标量。 2.2.2 聚合量 若一个数据可继续分解,则称为聚合量(Aggregate),比如 Java 对象就是聚合量。 2.2.3 标量替换 把一个Java对象拆散,根据程序访问情况,将其用到的成员变量恢复为原始类型来访问。 假如逃逸分析能证明一个对象不会被方法外部访问,并且该对象可被分解,那么程序真正执行时将可能不去创建该对象,而改为直接创建它的若干个被这方法使用的成员变量。 将对象拆分后:
2.2.4 适用场景 标量替换可视为栈上分配一种特例,实现更简单(不用考虑对象完整结构的分配),但对逃逸程度的要求更高,它不允许对象逃逸出方法范围内。 2.3 同步消除(Synchronization Elimination) 线程同步是个相对耗时的过程,若逃逸分析能确定一个变量不会逃逸出线程,即不会被其他线程访问,则该变量的读写肯定不会有线程竞争, 也可安全消除对该变量实施的同步措施。 逃逸分析的论文在1999年就已发表,但到JDK 6,HotSpot才开始初步支持逃逸分析,至今该也尚未成熟,主要因为逃逸分析的计算成本高到无法保证带来的性能收益会高于它的消耗。要百分百准确判断一个对象是否会逃逸,需进行一系列复杂数据流敏感的过程间分析,才能确定程序各个分支执行时对此对象的影响。过程间分析这种大压力的分析算法正是即时编译的弱项。试想,若逃逸分析完毕后发现几乎找不到几个不逃逸的对象, 那这些运行期耗用的时间就白费了,所以目前JVM只能采用不那么准确,但时间压力 (编辑:济源站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |