讲一下 Java 创建一个对象的过程。????#yyds干货盘点#

大鹏一日同风起,扶摇直上九万里。这篇文章主要讲述讲一下 Java 创建一个对象的过程。????#yyds干货盘点#相关的知识,希望能为你提供帮助。
讲一下 java 创建一个对象的过程。【????】【讲一下 Java 创建一个对象的过程。????#yyds干货盘点#】下图便是 Java 对象的创建过程,我建议最好是能默写出来,并且要掌握每一步在做什么。

讲一下 Java 创建一个对象的过程。????#yyds干货盘点#

文章图片

Step1:类加载检查
虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池(存在元空间)中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的< kbd> 类加载过程< /kbd> 。
Step2:分配内存
在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。
分配方式有 “指针碰撞” 和 “空闲列表” 两种,选择哪种分配方式由 Java 堆是否规整决定,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
内存分配的两种方式:(补充内容,需要掌握)
选择以上两种方式中的哪一种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 收集器的算法是" 标记-清除" ,还是" 标记-整理" (也称作" 标记-压缩" ),值得注意的是,复制算法内存也是规整的
  • 指针碰撞
    适用场合:堆内存规整〔即没有内存碎片)的情况下
    原理:用过的内存全部整合到一边,没有用过的内存放在另一边,中间有一个分界值指针,只需要向着没用过的内存方向将该指针移动对象内存大小位置即可
    GC收集器 :SerialParNew
  • 空闲列表
    适用场合:堆内存不规整的情况下
    原理﹔虚拟机会维护一个列表,该列表中会记录哪些内存块是可用的,在分配的时候,找一块儿足够大的内存块儿来划分给对象实例,最后更新列表记录。
    GC收集器:CMS3
内存分配并发问题(补充内容,需要掌握)
在创建对象的时候有一个很重要的问题,就是线程安全,因为在实际开发过程中,创建对象是很频繁的事情,作为虚拟机来说,必须要保证线程是安全的,通常来讲,虚拟机采用两种方式来保证线程安全:
  • CAS+失败重试: CAS 是乐观锁的一种实现方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。
  • TLAB: 为每一个线程预先在Eden区分配一块儿内存,JVM 在给线程中的对象分配内存时,首先在 TLAB 分配,当对象大于 TLAB 中的剩余内存或 TLAB 的内存已用尽时,再采用上述的 CAS 进行内存分配
    Step3:初始化零值
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
Step4:设置对象头
初始化零值完成之后,虚拟机要对对象进行必要的设置,【例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。】 这些信息存放在对象头中。 另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。
Step5:执行 init 方法
在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始,& lt; init& gt; 方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 & lt; init& gt; 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。
标记清除、标记复制、标记整理分别是怎样清理垃圾的?各有什么优缺点?【?????】 标记清除
可以看到,在对象可以被回收的区域上,JVM会直接把这些垃圾对象占用的内存直接清除掉。
优点:简单
缺点:造成内存空间碎片
讲一下 Java 创建一个对象的过程。????#yyds干货盘点#

文章图片

标记复制
标记-复制算法将原本的堆内存划分了两个区域,采用了“半区复制”算法,将一半的内存省出来,当发生垃圾收集行为时,将存活的对象复制到另外一半保留区域中连续存放。
优点:标记-复制算法的优点是解决了大对象分配内存的内存碎片问题,也解决了标记-清除算法中大量垃圾对象导致的清除效率问题。
缺点:也非常的明显,那就是可分配的内存空间少了整整一半,而且如果某次存活的对象较多,甚至全部存活,那么复制的效率将会非常低。
讲一下 Java 创建一个对象的过程。????#yyds干货盘点#

文章图片

标记整理
根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
讲一下 Java 创建一个对象的过程。????#yyds干货盘点#

文章图片

分代收集
当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。
一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
  • 比如在新生代中,每次收集都会有大量对象死去,所以可以选择”标记-复制“算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。
  • 而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。
关注公众号@孙中明 回复:3005
获取书籍
《深入理解Java虚拟机》
讲一下 Java 创建一个对象的过程。????#yyds干货盘点#

文章图片


    推荐阅读