JAVA知识点-Java对象的分配详解
本文最后更新于:May 26, 2022 am
积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里,不积小流无以成江海。齐骥一跃,不能十步,驽马十驾,功不在舍。面对悬崖峭壁,一百年也看不出一条裂缝来,但用斧凿,能进一寸进一寸,能进一尺进一尺,不断积累,飞跃必来,突破随之。
目录
Java中的对象并不都是分配在堆
中的,也有一部分是分配在栈
中的。
前置
Java运行时区域分为五大区:
程序计数器
虚拟机栈
本地方法栈
堆
方法区
其中,前三个是线程私有
的,后两个是线程共享
的。
对象分配
栈
首先通过new生成对象。然后判断是否可以分配在栈上。
之所以有些对象可以分配在栈中,主要是因为:当一个对象可以分配在栈中时,只要将对象弹出栈即表示对象结束,而无需垃圾收集器进行回收。
之所以不是所有对象都分配在栈上,主要原因有:
- 栈的空间比较小(256K)。
- 当一个栈帧A中引用了其他栈帧B的对象时,如果栈帧B弹出栈时,那么栈帧A中的引用就会出现空指针异常。所以就需要进行一个
逃逸分析
:通俗的说就是看此对象中是否存在有被其他地方所使用的引用。如果有,则不行,反之则可以。 - 标量替换。如果是一个无法再分解成更小的数据的数据(如基本数据类型),则可以分配在栈中。而引用类型则不可以。
堆
如果不能分配在栈中,那么就只能分配在堆中,但分配在堆中还会进行一些判断。
看对象是否大(如数组)。如果很大,则直接进入老年代,在老年代中会通过Full GC进行回收。
如果对象是小对象,则会在Eden区进行分配。而在Eden区又有两种情况:
- 会优先进行线程私有本地分配TLAB(Thread Local Allocation Buffer)
- TLAB失败后才再在Eden区中进行分配。
之所以会先进行TLAB,主要是因为线程的同步问题。例如:有多个线程,但都在同一块地方进行分配。那么就需要做好线程间的同步问题,而且一开始就进行同步,那么效率就不高。所以就先进行TLAB进行一个优化。
而TLAB优化:每一个线程在Eden区中都有一个独立的小空间,每一个线程分配对象时,优先在自己的空间中进行分配,而不会先占用公共区域,这样效率就会提高。只有当自己的独立空间不够时,才会在公共区域进行分配。如下图所示:
然后对象分配完成后,就是和GC有关的事了,这里就不详说了。这里贴两张也许有助于理解的图。
其他网图:
本文作者: 墨水记忆
本文链接: https://tothefor.com/DragonOne/46d0d953.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!