深入学习JVM03 类与对象 下篇
  dBFTbkVLMBge 2023年11月02日 54 0

11 对象创建

深入学习JVM03  类与对象 下篇_对象创建

类加载

深入学习JVM03  类与对象 下篇_对象创建_02

空间分配

深入学习JVM03  类与对象 下篇_对象创建_03

指针碰撞

深入学习JVM03  类与对象 下篇_内存分配_04

空闲列表

深入学习JVM03  类与对象 下篇_JVM_05

TLAB 线程本地缓冲区

TLAB 是 Thread Local Allocation Buffer 的缩写,也称为线程本地分配缓冲区。我们以垃圾回收器采用 CMS 为例,这种情况下,所有的对象都是在新生代 Eden 区分配的。因为 Eden 区也是全局共享的,当同一时间有多个线程同时向 Eden 区申请空间分配的时候,就必然会引发同步问题,从而导致内存分配效率降低。

为此 JVM 引入了 TLAB 机制,也就是以线程为单位,为每个线程分配一块区域以减少同步竞争,从而提升对象分配的效率

当然即使使用了 TLAB,也不会无限地给一个线程分配空间,因为在实际的生产环境中堆空间是非常宝贵的资源,所以 TLAB 分配的空间一般不会很大。我们可以通过 -XX:TLABWasteTargetPercent 来设置 TLAB 占用的空间大小。因为 TLAB 空间是有限的,所以很可能会出现分配的对象大小超过 TLAB 空间的情况。这种情况下有两种解决方案,第一种就是绕过 TLAB,直接在堆上分配,第二种就是废弃掉当前的 TLAB,创建一个新的 TLAB 来满足新分配的对象的空间要求。

深入学习JVM03  类与对象 下篇_对象创建_06

对象创建两段论

深入学习JVM03  类与对象 下篇_JVM_07

对象创建快捷流水线

深入学习JVM03  类与对象 下篇_对象创建_08

这条全新的流水线主要由四个节点构成

深入学习JVM03  类与对象 下篇_内存分配_09

深入学习JVM03  类与对象 下篇_内存分配_10

深入学习JVM03  类与对象 下篇_对象创建_11

深入学习JVM03  类与对象 下篇_内存分配_12

深入学习JVM03  类与对象 下篇_内存分配_13

深入学习JVM03  类与对象 下篇_对象创建_14

深入学习JVM03  类与对象 下篇_内存分配_15

深入学习JVM03  类与对象 下篇_内存分配_16

深入学习JVM03  类与对象 下篇_内存分配_17

12 JVM对象创建模式和最佳实践

JVM创建对象流程

深入学习JVM03  类与对象 下篇_JVM_18

深入学习JVM03  类与对象 下篇_对象创建_19

深入学习JVM03  类与对象 下篇_对象创建_20

对象在 JVM 中存在的形态

深入学习JVM03  类与对象 下篇_内存分配_21

Book 类对象存储在 JVM 里,总共由 3 个部分组成,分别是对象头、实例数据和对齐填充

深入学习JVM03  类与对象 下篇_对象创建_22

深入学习JVM03  类与对象 下篇_对象创建_23

深入学习JVM03  类与对象 下篇_内存分配_24

深入学习JVM03  类与对象 下篇_内存分配_25

我们可以用 -XX:+UseTLAB 来启用 TLAB,它在 JDK8 中是默认开启的。开启 TLAB 后,每个线程在创建对象时都会在自己的 TLAB 中进行,从而避免了不同线程间的内存分配竞争,提升了系统性能。反之,如果我们没有开启 TLAB,那么这 10 个线程都将在共有的 Eden 区进行内存分配,会存在较大的竞争和同步开销,系统性能将大大降低。

深入学习JVM03  类与对象 下篇_JVM_26

13 对象回收(上):定位待回收的对象

什么是 GC

GC 是 Garbage Collection 的缩写,中文叫做垃圾回收。它是一种自动化的内存管理机制,能够识别和回收不再使用的内存空间。在 Java 里,JVM 负责 GC。通过这种方式,Java 程序员无需手动进行内存的分配和回收,从而降低了内存泄漏的风险,提高了开发效率。

GC 的主要目标

深入学习JVM03  类与对象 下篇_JVM_27

GC 的主要步骤

深入学习JVM03  类与对象 下篇_内存分配_28

深入学习JVM03  类与对象 下篇_对象创建_29

深入学习JVM03  类与对象 下篇_内存分配_30

深入学习JVM03  类与对象 下篇_JVM_31

14 对象回收(下):垃圾回收算法

深入学习JVM03  类与对象 下篇_JVM_32

15 G1垃圾回收算法

深入学习JVM03  类与对象 下篇_内存分配_33

 JDK 11 及以上的版本中,G1 一骑绝尘,使用率占比达到 65% 。所以在这个 CMS 垃圾收集器逐步淡出历史舞台,而 ZGC 还未完全成熟的阶段,G1 垃圾收器注定将在未来的一段时间内扛起主流垃圾收集器的大旗,成为兼顾延迟与吞吐的最佳选择。而现实中,在 JDK 11 逐渐登上历史舞台的背景下,越来越多的系统,通过升级到 G1 以实现性能的提升

深入学习JVM03  类与对象 下篇_对象创建_34

G1 内存划分

G1 中的年轻代、老年代是一种逻辑划分,而不再是物理划分,也就是说年轻代和老年代不再是连续的内存地址空间,而是一组 Region 的集合。这里的 Region 是 G1 中最小内存分配单元,你可以通过 -XX:G1HeapReginotallow=n 来设置 Region 的大小,可以设定为 1M、2M、4M、8M、16M、32M。

JVM 中规定 Region 的大小必须是 2 的整数幂,并且不能超过 32M。如下图所示,当你采用 G1 作为垃圾收集器时,JVM 会将堆内存划分为一个个大小相同的 Region 进行管理。所以合理设置 Region 的大小,是用好 G1 的一个非常重要的因素

G1 采用的是分代收集和区域(Region)划分相结合的垃圾回收算法。在最小的物理内存单元是 Region 的基础上,依据分代收集算法,G1 将堆内存在逻辑层面划分为 4 个区域,分别是 Eden Space、Survivor Space、Old Generation 以及 Humongous Space。Eden Space 与 Survivor Space 的组合,就是我们通常说的年轻代,而 Humongous Space 是 G1 专门提出来的一个区域,用于专门存储程序中的大对象。

一个对象的大小如果超过了 Region 容量的一半,就会被直接存放至 Humongous 区域。当对象的大小远超 Region 大小的时候,JVM 会分配连续的 Humongous Region 用来存放这个对象。

深入学习JVM03  类与对象 下篇_JVM_35

基于上面提到的内存划分和垃圾回收算法,在 G1 中存在三种 GC 模式,分别是 Young GC、Mixed GC 和 Full GC。

深入学习JVM03  类与对象 下篇_对象创建_36

深入学习JVM03  类与对象 下篇_对象创建_37

深入学习JVM03  类与对象 下篇_JVM_38

定位一个待回收对象

 G1 定位待回收对象的时候,还有两个重要的工具,分别是 Remembered Set(记忆集)和 Card Table(卡表)

Remembered Set(记忆集)

每个 Region 都有对应的 Remember Set。主要记录某个 Region 里的对象被别的 Region 的对象引用的情况。这样,当开始扫描时,只需要将某个 Region 的 GC roots set 中加上 remember set,就能保证没有遗漏。

深入学习JVM03  类与对象 下篇_对象创建_39

Card Table(卡表)

Card Table 也是 G1 用于处理跨 Region 引用的一种方式,主要应用在并发标记阶段。Java 堆被分为很多小块,也叫做 Card(卡片),每张卡片默认大小就是 512Byte,每张卡记录了从某个地址开始连续 512 字节内存范围的变化情况。当在写入对象引用的时候,JVM 会把含有这个引用的卡标记为“dirty”,如果卡中的对象发生了改变,那么对应的卡就会被标记,这样在进行垃圾回收的时候,可以找出可能的跨区引用,避免引用丢失。

Remembered Set 和卡表的主要作用就是为了处理和跟踪跨 Region 引用关系,避免在进行局部垃圾回收时,出现引用丢失导致应用出错。这两个概念的使用无需程序员关心,都是由 JVM 和 G1 收集器自动完成的。但是正是借助记忆集和卡表的功能,G1 会在运行期间计算出每个 Region 回收的性价比。从而借助停顿预测模型,找出用户预期时间内最高回收收益的 Region 组合。

16 面向未来的垃圾回收 ZGC Shenandoah

ZGC 的由来

Oracle 决定开发一种全新的垃圾收集器,旨在提供低停顿时间、高可伸缩性和适用于大内存应用程序的解决方案。于是在 2017 年,Oracle 推出了名为 ZGC 的垃圾收集器,首先作为 Oracle JDK 的一个实验性功能引入。在随后的几个版本中,Oracle 对 ZGC 进行了改进和优化,不断增加新功能,提升性能,并解决了一些问题。最终,ZGC 在 JDK 11 中正式成为 Oracle JDK 的一部分,摇身一变,成为了一种稳定的垃圾收集器,并提供商业支持

ZGC 使用了读屏障技术来捕获引用关系的变化。除此之外,ZGC 也具有支持大型堆内存的功能,最高可达 16TB 的堆内存容量。这对于需要处理大量数据的应用程序非常有用。

深入学习JVM03  类与对象 下篇_内存分配_40

ZGC 是一种专为高并发和大内存应用场景设计的垃圾收集器,具备可伸缩性、低停顿时间、大堆内存支持和易用性等特点

ZGC VS G1

深入学习JVM03  类与对象 下篇_内存分配_41

深入学习JVM03  类与对象 下篇_对象创建_42

ZGC的黑科技:颜色指针

深入学习JVM03  类与对象 下篇_JVM_43

深入学习JVM03  类与对象 下篇_JVM_44

ZGC的垃圾回收过程

深入学习JVM03  类与对象 下篇_内存分配_45

深入学习JVM03  类与对象 下篇_对象创建_46

ZGC的最佳实践

深入学习JVM03  类与对象 下篇_对象创建_47

深入学习JVM03  类与对象 下篇_JVM_48

Shenandoah 垃圾回收器

深入学习JVM03  类与对象 下篇_内存分配_49

深入学习JVM03  类与对象 下篇_内存分配_50

17 JVM扩展机制

在 Java 中,常见的扩展机制有接口、抽象类、反射、SPI 等

允许我们在不改变原有代码的基础上进行功能的扩展

扩展机制的实现方式是多样的,接口、抽象类都可以用于定义公共的方法,供其他类实现或者继承;反射则可以在运行时动态地创建对象和调用方法;动态代理则可以在运行时动态地创建和控制对象的行为;SPI 则是 Java 提供的一种服务提供发现机制,它允许第三方为一个产品或者一个服务提供插件

接口和抽象类

接口是 Java 里的一种核心机制,它主要负责定义对象的行为协议。这里的协议,你可以理解成规定的一种标准,或者说是一种约束。接口就是规定了一种方法的集合,而这些方法如何实现,就由实现接口的类来决定。接口在 Java 里的特殊之处在于,一个类可以实现多个接口,这就有力地支持了 Java 的动态特性。

反射

深入学习JVM03  类与对象 下篇_对象创建_51

深入学习JVM03  类与对象 下篇_对象创建_52

SPI

深入学习JVM03  类与对象 下篇_内存分配_53

深入学习JVM03  类与对象 下篇_内存分配_54

深入学习JVM03  类与对象 下篇_内存分配_55

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  zzJeWaZlVwfH   2023年11月02日   57   0   0 常量池方法区jvm
  dBFTbkVLMBge   2023年11月02日   86   0   0 javajvm
  dBFTbkVLMBge   2023年11月12日   30   0   0 jvm
dBFTbkVLMBge