浅谈类加载过程

前言

相信任何一个JAVA爱好者或者是程序员都知道大致的JAVA程序加载流程:

编辑源程序 --> 编译生成字节码文件 --> 解释运行字节码文件

但是这样解释经不起细问,编译是怎么编译的?字节码文件怎样生成?解释运行字节码文件你怎么解释,又怎样运行?其中有哪些流程?又有哪些加载器起到了作用?作用是什么?…
这个,就需要我们进行细纠,而本篇博客,笔者也会尽力从目前所能了解到的知识的角度对这些问题进行一一解答。
在进行具体的解答之前,先给出图示(我知道我画的丑),各位读者大大可以对照着图阅读。
在这里插入图片描述

一丶编译阶段

在编译阶段的主要任务就是将 .Java文件编译生成.class文件,而这一过程由JAVAC编译器来完成,
JAVAC编译器是个啥?

这是一个由纯JAVA语法编写的一个编辑器。作用大概如下:
1.按照JAVA语言语法对源文件检测,看看是否违规
2.如果不符合规范,那么报错
3.如果符合规范,那么按照字节码的文件规范生成对应的字节码文件。

其中具体细分为以下四个阶段。

1>词法分析

词法解析是编译器执行的字节码编译的第一步。主要就是将代码中的语句分割成一个一个的符号,再仔细一点,就是将JAVA源程序里面的标识符和关键字等转化为一个一个的Token序列
词法解析器的接口是javac.parser.Lexer ,它属于同包下Scanner类的子类,它的主要任务是按照单个字符的方式读取Java源文件中的关键字和标识符等,然后将其转换为符合Java规范的Token序列。
而Token其实就是一个枚举类型,其内部定了许多符合Java语法规范并与源码字符集相对应的枚举常量。

2>语法分析

语法分析的目的就是将经过词法分析得到的Token整合为一棵结构化的抽象语法树
负责词法解析工作的是javac.parser.JavacParser类。
而检测工作则有以下方法来完成:

(1) qualident() 方法解析 package 语法节点

(2)importDeclaration() 方法解析 import 语法树

(3)调用 classDeclaration() 方法解析 class 语法树

3>语义解析

语法树生成了,但是百炼成钢,接下里这颗树还要被不断修整。语义解析会将这颗不够完善的语法树扩充地更加完善
并且对这课语法树进行检测,看它符不符合JAVA语义要求
具体步骤:

1.为没有构造方法的类型添加默认的无参构造函数
2.检查任何变量是否在使用之前都被初始化过
3.检查变量类型和值是不是匹配
4.将String类型和常量进行合并处理
5.检查代码中的操作是不是都可达
6.异常检查
7.将语法糖的内容正常化

4>字节码生成器

到了这一步,我们的字节码文件才可以差不多算是一个完整的宝宝,那接下来,就应该调用javac.jvm.Gen类,将这棵语法树编译为Java字节码文件
到了这一步,字节码文件才算真正的生成,可编译是编译完了,问题是现在还没有解决地址问题,那么怎么办?那接下来它就要被类加载系统抱走准备继续深造了。

=======================================================
这里咋们可以大致来查看一下字节码文件的规范。

(该规范来源于JAVA官方对于字节码文件规范的叙述,出处:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html)

在这里插入图片描述

二丶加载阶段

加载阶段的主要是任务是:通过一个类的全限定名,然后用类加载器加载成生成对应的二进制字节流,并且在内存中生成该类的java.lang.class对象,用于类的各种数据的访问入口
这里给一下几种类加载器的工作原理

(此处对于类加载器的总结来源于囧辉大佬,@程序员囧辉)

1>启动类加载器(Bootstrap ClassLoader)

这个类加载器负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。

2> 扩展类加载器(Extension ClassLoader)

这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

3> 应用程序类加载器(Application ClassLoader)

这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

4> 自定义类加载器:

用户自定义的类加载器

三丶链接阶段

1> 验证

这里的验证主要是就是验证对应的二进制字节流是否符合JAVA虚拟机的语法规范以及安全性能的检查
包括对于文件格式的验证,对于元数据的验证,对于字节码,符号引用等等的验证。

2> 准备

准备就是在内存上给这个类当中的静态变量开辟空间并且初始化,这里的初始化指的就是通常情况下,各个数据类型的对应的默认值。

PS:这里的初始化可以看之前博客----数组,里面对应的初始化和此处相同。

3>解析(重要步骤,这里就是给地址了)

解析指的是把常量池当中的符号引用替换为直接引用
什么意思?

比如说,我现在有一个方法 myWorld () ,它的内存地址是 0x10086,符号引用就是 myWorld(),但是直接引用就是 0x10086(话费查询直通车…)

四丶初始化

初始化阶段,会将类中的JAVA初始化代码开始执行。主要就是静态变量的赋值以及静态代码块(static { } )中的语句,换句话说这就是一个执行类构造器的过程,并且只对static修饰得到变量或者语句进行初始化
这里要注意,如果包含多个静态代码块,则会按照从上而下的顺序将这些静态代码块合并成为 < clinit >。具体程序运行如下:
在这里插入图片描述

结果如下:
在这里插入图片描述

可以看到,静态代码块只会在类初始化阶段只执行一次,而实例代码块在每一个对象初始化的阶段都会执行并且只执行一次。接下来再具体:

实例代码块:
在这里插入图片描述

静态代码块:
在这里插入图片描述

可以看到,静态代码块被根据定义次序合并成了 < clinit >,而实例代码块,就和我上一篇博客讲的一样,被和构造代码块合并在了一起,并且在构造代码块之前。
而如果此类还有父类,那么具体执行流程为:

父类静态变量(代码块) --> 子类静态变量(代码块)–> 父类非静态变量(构造器)–> 父类构造器 --> 子类非静态变量(代码块) --> 子类构造器

五丶总结

这就是JAVA对程序猿的宠爱嘛~~

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
cache memory(缓存内存)是计算机系统中重要的组成部分,用于提高CPU的访问速度和整体性能。它由高速存储器和相关的控制逻辑组成,位于CPU和主存储器之间。cache memory将最频繁使用的数据和指令存储在靠近CPU的高速存储器中,以便快速访问。 cache memory的设计目标是解决CPU与主存储器之间的速度差异。由于主存储器的访问速度较慢,当CPU需要读取或写入数据时,cache memory会首先检查自己的高速存储器中是否已经保存了需要的数据。如果有,那么就直接从cache memory中读取数据,避免了访问主存的延迟。而如果cache memory中没有需要的数据,则CPU再去访问主存储器。 cache memory采用了局部性原理,即程序执行时,存在频繁访问的数据和指令的局部性特点。这些频繁访问的数据和指令存储在cache memory中,使得CPU的访问速度变得更快。cache memory通过高速存储器和替换算法来提供快速访问,并且通过预取技术可以预先将可能需要的数据加载到cache memory中,减少了指令的等待时间。 在计算机系统中,由于程序执行过程中存在大量的重复访问和数据的无效读写,cache memory能够有效地提高整体性能。但是,cache memory的容量有限,如果数据在cache memory中不存在,就需要去主存储器中读取,会引发cache miss(缓存未命中)问题。cache miss会导致CPU需要等待数据的加载,从而降低了性能。 因此,在设计计算机系统时,需要综合考虑cache memory的容量、速度、替换算法等因素,以达到合理的设计。cache memory的优化和管理是一个复杂的工程,需要根据具体应用的特点来进行适当的配置和调整,以实现最佳的性能提升。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值