Java New对象分配内存流程
一、流程图
二、流程介绍
1、进行逃逸分析,判断是否能够分配到栈上:
Y: 如果能分配到栈上,则进行分配。等方法出栈时,对象内存销毁,可有效减少GC的次数。
N:无法分配到栈上,则判断是否是大对象,通过一个参数来判断对象大小,如果对象内存大则直接分配到old区。最后old区进行FGC结束。如果不够大则进入TLAB,就是伊甸区。
2、伊甸区:分TLAB、S1、S2。如果进行GC机制,没清除到的则进入S1。
5、S1如果进行GC清除,没清除到的对象进入S2。
6、S2如果进行GC清除,没清除到的对象进入S1,循环流程。如果年龄够大的则进入OLD区,老年代,这里进行的是动态年龄判断,动态对象年龄判断,主要是被TargetSurvivorRatio这个参数来控制。而且算的是年龄从小到大的累加和,而不是某个年龄段对象的大小。
7、OLD区,就是老年代都是顽固分子,等老年代满了进行FGC
三、什么是逃逸分析
1.为什么要分配在栈上?
通过JVM内存模型中,我们知道Java的对象都是分配在堆上的。当堆空间(新生代或者老年代)快满的时候,会触发GC,没有被任何其他对象引用的对象将被回收。如果堆上出现大量这样的垃圾对象,将会频繁的触发GC,影响应用的性能。其实这些对象都是临时产生的对象,如果能够减少这样的对象进入堆的概率,那么就可以成功减少触发GC的次数了。我们可以把这样的对象放在栈上,这样该对象所占用的内存空间就可以随栈帧出栈而销毁,就减轻了垃圾回收的压力。
2.什么情况下会分配在栈上?
为了减少临时对象在堆内分配的数量,JVM通过逃逸分析确定该对象会不会被外部访问。如果不会逃逸可以将该对象在栈上分配内存。随栈帧出栈而销毁,减轻GC的压力
3.什么是逃逸分析?
逃逸分析:就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,
如果没有被外部的方法使用,那么就建议在栈中分配一块内存空间,用来存储临时的变量。
如果被外部的方法引用了,那就在堆上分配内存空间,实现共享。
JDK 1.6就已经使用逃逸分析了。
四、什么是大对象
在Java中,大对象是指占用大量内存空间的对象。具体来说,如果一个对象的大小超过了堆内存的一半,那么它就被认为是一个大对象。
大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。
五、什么是TLAB
TLAB的全称是Thread Local Allocation Buffer,翻译过来就是线程本地分配缓存。
首先从Thread
Local这两个单词能够联想到一个本地线程变量类ThreadLocal,该类可以用来维护线程私有变量,而TLAB则是一个线程专用的内存分配区域,也是线程私有的。
1、那为什么需要TLAB呢?
在日常的业务过程中,Java对象会不断的被新建和不断的被回收,这就涉及到对象的分配了,而新建的对象一般都是分配在堆上,而堆却是线程共享的。所以如果同一时间,有多个线程要在堆上申请空间,这里可以类比多线程访问共享变量的操作,要保证共享变量的线程安全,就得采取线程安全的手段。所以每一次对象分配都要做同步,而越多的线程要在堆上申请空间,竞争就会越激烈,效率就会降低。因此Java虚拟机采用了TLAB这种线程专属的区域来避免出现多线程冲突,提高对象分配的效率。TLAB是默认启动的,在该情况下,JAVA虚拟机会为每一个线程都分配一个TLAB区域。
2、TLAB区域在堆中的哪个区域?
Eden区,因为eden区一般是新建对象所在的区域(这里去除大对象,因为大对象会直接进入老年代)