深入学习JVM02 类与对象 上篇
  dBFTbkVLMBge 2023年11月02日 37 0

06 类加载的流程

类加载子系统可以看作是 JVM 的搬运工。通过使用 Javac 编译器,我们将编写的代码转换为.class 文件,这样类就可以被真正地加载到 JVM 中,从而实现高效地运行。借助类加载流程,我们将.class 文件中的数据结构存储到了运行时的方法区中,作为后续 Java 程序运行的基础。

深入学习JVM02  类与对象 上篇_JVM

深入学习JVM02  类与对象 上篇_方法区_02

因为方法区里存储了类的元数据和静态变量等,所以平时在开发的时候你需要关注方法区的内存使用,避免大量加载类以及定义过多的静态变量导致内存不足。最后还要避免类初始化的循环引用,创建类时,确保类之间的引用关系没有循环,否则可能导致类初始化阻塞。

深入学习JVM02  类与对象 上篇_方法区_03

类加载全流程

深入学习JVM02  类与对象 上篇_方法区_04

深入学习JVM02  类与对象 上篇_JVM_05

深入学习JVM02  类与对象 上篇_方法区_06

深入学习JVM02  类与对象 上篇_类加载_07

深入学习JVM02  类与对象 上篇_JVM_08

深入学习JVM02  类与对象 上篇_JVM_09

07 类加载子系统 自定义加载器

深入学习JVM02  类与对象 上篇_类加载_10

深入学习JVM02  类与对象 上篇_方法区_11

深入学习JVM02  类与对象 上篇_方法区_12

深入学习JVM02  类与对象 上篇_类加载_13

深入学习JVM02  类与对象 上篇_方法区_14

深入学习JVM02  类与对象 上篇_方法区_15

深入学习JVM02  类与对象 上篇_方法区_16

深入学习JVM02  类与对象 上篇_JVM_17

深入学习JVM02  类与对象 上篇_JVM_18

深入学习JVM02  类与对象 上篇_类加载_19

深入学习JVM02  类与对象 上篇_方法区_20

深入学习JVM02  类与对象 上篇_类加载_21

08 反射机制

深入学习JVM02  类与对象 上篇_方法区_22

反射

反射(Reflection)是 JVM 提供的运行时机制 ,它允许程序在运行期借助  Reflection API 动态加载类或获取任何类的内部信息,动态创建对象并调用其属性,即使对象类型在编译期还是未知的。而我们通常写的程序,对象的类型是在编译期就确定下来的。就像上面说到的饭店的菜单,每道菜品是固定的,无法变更。

而反射赋予了我们动态创建菜品和调整菜品的能力。所以说,虽然 Java 是一种静态语言,但是反射机制的存在使 Java 也具有了动态性,具备了运行时自我认知的能力。这样我们就可以在运行时观察甚至修改 JVM 的行为。就像进入饭店的后厨,可以观察甚至调整我们的菜品。

深入学习JVM02  类与对象 上篇_方法区_23

反射的实现原理

深入学习JVM02  类与对象 上篇_类加载_24

这个 Class 对象就是反射机制的核心,它就像打开 JVM 这个厨房的钥匙,赋予了我们打造专属于自己的菜品的能力

反射 API

深入学习JVM02  类与对象 上篇_类加载_25

深入学习JVM02  类与对象 上篇_JVM_26

深入学习JVM02  类与对象 上篇_JVM_27

// 沙拉酱版本的蘸酱小黄瓜
public static  DippedSauceCucumbers  createCustomizedFood() throws Exception{
 
    //第一步:获取Class对象,就像拿到了进入饭店后厨的钥匙
    Class dippedSauceCucumbersClass = DippedSauceCucumbers.class;
 
    //第二步:用反射的方式生产一个DippedSauceCucumbers对象,就像我们去后厨自己做了一份蘸酱小黄瓜
    Object dippedSauceCucumbers = dippedSauceCucumbersClass.newInstance();
 
    //第三步:因为已经身在厨房,我们可以随意调换成我们喜欢的酱料,小小的菜单已经不能约束我们丰富的想象力了 ^_^
    Field dippingSauceField = dippedSauceCucumbersClass.getDeclaredField("dippingSauce");
    dippingSauceField.setAccessible(true);
    dippingSauceField.set(dippedSauceCucumbers,"沙拉酱");
 
    //第四步:基于我们调换的酱料,重新生成沙拉酱版本的蘸酱小黄瓜的菜单
    Method setMenuMethod = dippedSauceCucumbersClass.getDeclaredMethod("setMenu");
    setMenuMethod.setAccessible(true);
    setMenuMethod.invoke(dippedSauceCucumbers);
 
    return  (DippedSauceCucumbers)dippedSauceCucumbers;
}
 
public static void main(String[] args) throws  Exception {
    DippedSauceCucumbers dippedSauceCucumbers =  DippedSauceCucumbers.createCustomizedFood();
    dippedSauceCucumbers.printMenu();
}

深入学习JVM02  类与对象 上篇_类加载_28

反射 API 详解

深入学习JVM02  类与对象 上篇_JVM_29

深入学习JVM02  类与对象 上篇_方法区_30

深入学习JVM02  类与对象 上篇_类加载_31

深入学习JVM02  类与对象 上篇_JVM_32

深入学习JVM02  类与对象 上篇_JVM_33

反射应用场景

深入学习JVM02  类与对象 上篇_方法区_34

深入学习JVM02  类与对象 上篇_类加载_35

第二步:Spring 通过反射设置属性值。在 BeanPostProcessor 后置处理器中,Spring 会读取属性配置,使用反射调用 set 方法为 Bean 的属性设置值。

第三步:Spring 通过反射调用 Bean 的生命周期回调方法,如 init-method 和 destroy-method。

深入学习JVM02  类与对象 上篇_方法区_36

09 SPI机制

SPI(Service Provider Interface)是一种服务发现机制,它允许应用程序在运行时动态地发现和加载实现某个接口的服务提供者。这里有两个关键词需要你特别关注,分别是“运行时”和“动态”。

深入学习JVM02  类与对象 上篇_类加载_37

深入学习JVM02  类与对象 上篇_方法区_38

SPI原理

基于“约定大于配置”的设计思想,SPI 通过在类路径下预先定义好接口和服务提供者的实现类,使应用程序可以在运行时自动发现和使用这些服务,而无需手动配置

深入学习JVM02  类与对象 上篇_方法区_39

深入学习JVM02  类与对象 上篇_方法区_40

深入学习JVM02  类与对象 上篇_方法区_41

SPI设计思想

深入学习JVM02  类与对象 上篇_JVM_42

深入学习JVM02  类与对象 上篇_JVM_43

手写一个SPI程序

深入学习JVM02  类与对象 上篇_JVM_44

深入学习JVM02  类与对象 上篇_类加载_45

深入学习JVM02  类与对象 上篇_JVM_46

深入学习JVM02  类与对象 上篇_方法区_47

深入学习JVM02  类与对象 上篇_方法区_48

深入学习JVM02  类与对象 上篇_方法区_49

在平台中使用

目前同一个接口已经有了两种实现方式,接下来就是在平台上注册和使用他们的时候了,你可以看一下平台层的代码。

深入学习JVM02  类与对象 上篇_方法区_50

深入学习JVM02  类与对象 上篇_JVM_51

深入学习JVM02  类与对象 上篇_类加载_52

10 JVM内部实现机制

JVM对象基础协议

深入学习JVM02  类与对象 上篇_类加载_53

深入学习JVM02  类与对象 上篇_方法区_54

深入学习JVM02  类与对象 上篇_类加载_55

深入学习JVM02  类与对象 上篇_方法区_56

深入学习JVM02  类与对象 上篇_类加载_57

深入学习JVM02  类与对象 上篇_JVM_58

深入学习JVM02  类与对象 上篇_类加载_59

深入学习JVM02  类与对象 上篇_类加载_60

如果数据存储的时候未按照地址对齐,很可能出现一种情况,就是当 CPU 读取的数据存在于 0x0002-0x0005 的地址空间,而 CPU 要想读取该数据时,需要先要把地址空间是 0x0000-0x0003 的数据读取出来,再把地址空间是 0x0004-0x0007 的部分读取出来,把不需要的数据去掉才能读取到需要的数据,显然这种方式是非常低效的,所以为了提升 CPU 的效率,在虚拟机里一般会设置默认对齐位。

在 HotSpot 里这个值是 8。HotSpot 虚拟机要求所有的对象大小都是 8 字节的倍数,对象填充区域起到的就是补齐填充的作用,这也是一个很经典的以空间换时间思想的应用

JVM 的 OOP-Klass 模型。这里的 oop 是 ordinary object pointer 的缩写,意思就是普通对象指针。相比于 C++,JVM 通过 oop 实现指针的对象化,并且使用直接指针,JVM 定位到内存中对象的效率非常高

深入学习JVM02  类与对象 上篇_方法区_61

深入学习JVM02  类与对象 上篇_方法区_62

深入学习JVM02  类与对象 上篇_类加载_63

深入学习JVM02  类与对象 上篇_方法区_64

ColorBook 拷贝了一份 Book 函数表,使它的函数表指针指向新的函数表,因为 ColorBook 覆写了 Book 的函数 print(),所以把函数表里覆写函数的函数指针替换成了 ColorBook 覆写的函数指针,而被调用函数在函数表里偏移量是固定的,这就是多态功能的原理。


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

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

暂无评论

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