跟我一起学JVM(二)——Java对象的幕后

今天的学习内容为Java对象的创建,内存分配以及访问。

我们都知道在Java程序中使用new关键字能够为我们创建一个对象实例,并且能按照我们的需要去进行一系列的对象初始化工作,但是很少有人愿意探究这个对象构建背后的过程。本文第一部分就是详细解读一个对象是如何被创造的。

(一)对象的创建

为了更好的理解,对象的创建过程将通过流程图来展示:
在这里插入图片描述
我们平时只会使用new,而一个new背后其实是这样的工作机制,这是值得我们深入学习的。

(二)对象的内存分配

对象内存分配流程图
在这里插入图片描述
我们可以根据实际的研发需要设置改变Java虚拟机的相关参数,比如占空间多少的对象可以被定义为大对象,新生代的最大年龄是多少等等。具体的内存分配细节又可如下展开:

  1. 在Eden先进行分配,若空间不够则进行Minor GC(指新生代中的GC)
  2. 大对象(长字符串以及数组等)直接进入老年代,因为对象占用空间大,新生代空间少,并且新生代采用的复制算法对于大对象效率低下。
  3. 长期存活的对象将进入老年代
    如何判断一个对象属于长期存活?使用对象年龄计数器,经过MinorGC并存活的对象将被移动到survivor中,并且对象年龄为1,对象在survivor中每安全度过一次Minor GC,年龄就增加1,到一定年龄后(默认15岁)则进入到老年代中。
    动态对象年龄的判定
  4. 如果survivor空间中相同年龄的所有对象大小总和大于survivor的一半,年龄大于或等于该年龄的对象就可以直接进入老年代了,不需要一定达到默认值15岁才进入。
  5. 空间分配担保,发生Minor GC之前。虚拟机会优先检查老年代最大可用连续空间是否大于新生代所有对象的总空间,如果条件成立,则Minor GC是安全的,否则将查看HandlePromotionFailure设置值是否允许担保失败。每次都是采用一次垃圾回收后能晋升到老年代对象容量的平均大小值作为经验值,与老年代的剩余空间进行比较,来确认是否进行Full GC(发生在老年代的GC,速度比Minor GC 慢10倍)。

(三)对象的访问途径

  1. 在Java堆设立句柄池和实例池,句柄池用来存储指向实例池和方法区对象类型数据的指针
  2. 采用直接指针方式,Java堆存放对象实例数据,在对象实例数据中存放到对象类型数据的指针

注意:直接指针访问速度更快,但是需要额外的空间存储对象类型数据指针。

对象的背后蕴藏着计算机科学家们对于内存优化的极致追求,这章知识也是为后面的垃圾收集算法与垃圾收集器打好基础。

预告:下一期的学习内容为垃圾收集算法与垃圾收集器

喜欢的话请关注点赞转发三连哦~


Instagram: https://www.instagram.com/barrywzc/
Twitter: https://twitter.com/BarryWa34098316
Bilibili: https://space.bilibili.com/473161964
GitHub: https://github.com/wzcwzcwzc
Patreon: https://www.patreon.com/wzcspace
WeChat: wzcspace


Please leave a LIKE and SUBSCRIBE for more content!
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章