【JVM笔记】-类加载子系统

类加载器子系统

字节码文件在类加载器子系统中主要经过三个阶段:

加载阶段:(引导类加载器也叫启动类加载器 Bootstrap ClassLoader,扩展类加载器Extension ClassLoader,系统类加载器System ClassLoader)

链接阶段:(验证 ,准备,解析)

初始化阶段;

类加载器子系统负责从文件系统或者网络中加载class文件,class文件在文件开头有特定的文件标识。

类加载器(Class Loader)只负责class文件的加载,至于是否可以运行,由Execution Engine(执行引擎)决定。

加载的类信息存放于方法区,除了类的信息外,方法区中还会存放运行时的常量池信息(class文件中的常量池(反编译可以看到)),可能还包括字符串字面量和数字常量。

class文件经过类加载子系统加载到JVM中,生成一个DNA元数据模板,放在方法区,并且可以根据这个元数据模板,调用其构造器,创建多个对象实例存放在堆空间中

类的加载过程1:加载

加载:

1、通过一个类的全限定名获取定义此类的二进制字节流

2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

3、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口(由此可见.class其实也是一个Java对象,所以在多线程中同步代码块可以使用一个类的Class作为同步监视器)

加载.class文件的方式:

1、本地加载

2、网络获取,Web Applet

3、从zip压缩包中读取,jar、war包的基础

4、运行时计算生成

5、由其他文件生成(JSP)

6、从数据库中

7、从加密文件中读取

类的加载过程2:链接

1、验证

确保class文件的字节流中包含的信息符合虚拟机要求,保证被加载类的正确性,前面提到字节码文件的起始信息都应该时相同的(同种语言的情况下)(java语言的开头:CA FE BA BE)

验证方式:文件格式验证,元数据验证,字节码验证,符号引用验证

2、准备

类变量分配内存并且设置该类变量的默认初始值,即零值

注意:

(1)这里不包含用final包含的static,因为其在编译的时候就已经分配了内存,这里会进行显示初始化(确定好数值,常量)。

(2)这里不会为实例变量分配初始化(还没有创建对象,对象属性不确定),类变量会分配在方法区中,而实例变量会随着对象一起分配到Java堆中。

3、解析

将常量池内的符号引用转换为直接引用的过程

事实上,解析操作往往会伴随着JVM在执行初始化之后再执行

符号引用就是一组符号来描述所引用的目标,符号引用的字面量形式明确定义再《Java虚拟机规范》的Class文件格式中。

直接引用就是直接指向目标的指针,相对偏移量或一个间接定位到目标的句柄。

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型。

类的加载过程3:初始化

初始化就是执行类构造器方法<clinit>()的过程。

此方法不需要定义,是javac编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并而来。

构造器方法中指令按语句在源文件中出现的顺序执行。

<clinit>()不同于类的构造器

若该类有父类,则父类的<clinit>()要先执行完毕

虚拟机必须保证一个类的<clinit>()方法在多线程下被同步加锁

类加载器的分类

JVM支持两种类型的类加载器:

引导类加载器(Bootstrap ClassLoader);

自定义类加载器(User-Defined ClassLoader);

从概念上讲,自定义类加载器一般指的是程序中由开发人员自定义的一类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。

无论类型如何划分,我们最常见的类加载器只有三个:

系统类加载器(C++编写 加载用户自定义类、java应用所有类类)、扩展类加载器(Java编写 加载类库 ext目录中的类(核心包之外的扩展类包))、引导类加载器(加载核心类库)

对于用户自定义类来说,类加载器是系统类加载器,对于核心类库()来说,使用引导类加载器进行加载。

为什么要自定义类加载器

1、隔离加载类,防止jar包中类冲突,实现类仲裁

2、修改类加载的方式

3、扩展加载源

4、防止源码泄露

关于ClassLoader

ClassLoader类是一个抽象类,其后所有的类加载器都继承于ClassLoader,除了引导类加载器(因为引导类加载器是C++编写的)

双亲委派机制

Java虚拟机对Class文件采用按需加载的方式,也就是说什么时候需要什么时候将它的Class文件加载到内存中生成Class对象。

而当加载某个类的Class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。

工作原理:

1、如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是委托给自己的父类加载器加载,一层一层往上递交请求,最终到达顶层的引导类加载器。

2、如果父类可以完成类的加载,就返回,如果不能完成类的加载任务,子加载器才会区尝试自己去加载。

优势:

1、避免类的重复加载

2、保护程序安全,防止核心api被窜改(沙箱安全机制)

知识点:

在JVM中两个对象是否是同一个对象实例的条件:

1、全限定类名相同

2、加载这个类的ClassLoader相同

这些信息会和加载的类的信息一起放在方法区中



posted @ 2020-08-18 17:44  枫叶藏在眼眸  阅读(89)  评论(0)    收藏  举报