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://www.processon.com/view/link/623806e75653bb071e724e6b


本文作者: 墨水记忆
本文链接: https://tothefor.com/DragonOne/46d0d953.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!