JVM类加载竟然如此简单,不敢相信

1:什么是类加载

虚拟机把类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制.

在Java语言中,类型的加载,连接和初始化过程都是在程序期间完成的,这种策略虽然会令类加载时稍微增加一些性能开销,但是会为java应用程序提供高度的灵活性,天生可以动态扩展的语言特性就是依赖运行时期动态加载和动态连接的这个特点实现

类加载在虚拟机的生命周期,加载,验证,准备,解析,初始化,使用,卸载七个阶段,其中,验证,准备,解析三个部分称之为连接类的加载, 分为加载是,验证,准备,解析,初始化,使用,卸载
在这里插入图片描述
类加载过程
1:加载

	在加载阶段,虚拟机需要完成以下3件事情
		1:通过类的全限定名来获取此类的二进制节流
		2:将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
		3:在内存种成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口,注
		加载和连接的部分内存是交叉进行的,记载尚未完成,连接阶段可能已经开始,比如部分字节码文件格式验证

2:连接-验证

	连接验证验证,是连接的第一步(共三步),这一阶段主要是为了确保class文件的字节流
	种包含的信息符合虚拟机的要求,并且不会在运行是不危害虚拟机,如没有经过代码检
	测的代码,就有可能会危害虚拟机,但我们现在其实验证是重复验证,因为现在很多工具
	也都有验证的,所以如果为能行想要提高加载数据,也能通过明白把加载验证关闭,不进
	行验证
	 **-Xverify:none 参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间**

3:连接-准备

	 准备阶段是正式为类变量分配内存并设置类变量初始化值的阶段,这些变量所使用的内存都将在方法区中进行分配,
	 这时候进行内存的仅包括类变量(satic修饰的),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中;

4:连接-解析

	 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程
	符号引用(Symbolic References):以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义
的定位到目标即可.符号引用与虚拟机的内存布局无关,引用的目标并不一定加载到内存中。在 Java 中,一个 java 类将会编译成一个
class 文件。在编译时,java 类并不知道所引用的类的实际地址,因此只能使用符号引用来代替.
直接引用是和虚拟机的布局相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引
用,那引用的目标必定已经被加载入内存中了。

5:初始化

	这一阶段虚拟机将开始正式执行类里面的代码了,初始化阶段执行类构造器<clinit>()方法的过程
	类构造器<clinit>()方法有编译器自动收集类中的所有类变量的赋值动作和statis语句和并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块中只能访问到定义的静态语句块之前的变量,定义在其之后的变量,在静态语局块中可以赋值,但是不能访问

6:使用

	通过上一步骤初始化,类里面代码已经在虚拟机生成内存,栈帧了,用户请求可以直接调用了

7:卸载

	生命的最后一步骤,被QC收回

2:类加载器

HotSpot团队把类记载阶段中的"通过一个类的全限定名来获取描述类的二进制字节流",这一个动作放在了虚拟机外面去实现.以便让应用程序自己来决定如何去获取所需要的类.这个动作的代码模块成为"类加载器"

Java当前这么流行,很大一块基石,是类加载器.类加载器它在OSGI,热部署,代码加密等领大方异彩类加载器虽然只用于一个类的加载动作,但是它在Java程序中起到的作用远远不限于类加载阶段,对于任意一个类,都需要有加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间

2.1 类加载器的分类

在Java虚拟机中,只存在两种不同的类加载器,一个是启动类加载器(Bootstrap classloader),c/c++语言实现,是虚拟机自身的一部分,另一种就是所有其他的类加载器,这些使用加载器都由Java语言实现,独立与虚拟机外部,并且父类都是Java.lang.ClassLoader

从 java 开发人员的角度来看,类加载器还可以划分得更细致一些.启动类加载器(Bootstrap ClassLoader):负责将存在于<JAVA_HOME>\lib 目录中,或者配置参数-Xbootclasspath 参数指定的路径中,并且能够被虚拟机识别(名字不符合的,就算放在了lib中也不会被夹在)的类库加载到虚拟机内存中.该类加载器无法被java程序直接引用.
扩 展 类 加 载 器 (Extension ClassLoader): 这 个 加 载 器 由 sun.miscLauncherKaTeX parse error: Undefined control sequence: \lib at position 41: …加 载 <JAVA_HOME>\̲l̲i̲b̲\ext 目录中,或者被 ja…AppClassLoader 实现.也称之为系统类加载
器.它负责加载用户类路径(classpath)上所指定的类库,开发者可以直接使用.一般情况下,这个就是程序中默认的类加载器.
我们程序都是由这三种类加载器互相配合进行加载的,如果有必要,还可以加入自定义的类加载器.
z
2.2双亲委派机制

对与类的加载,只需要加载虚拟机内存中一次就行了,为了避免重复加载,虚拟机会做以下处理,当父记载器ClassLoader已经加载到该类的时候,下面的子类就没必要在加载了,这种处理关系,叫做双亲委派模型

双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应该有自己父类加载器,如果一个类加载收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,没一个层次的类记载器都是如此,因此所有的加载 请求最终都应该传给负类的启动类加载器种,只有当父类反馈自己完不成这个请求,子类才会尝试去加载

在这里插入图片描述

2.3 破坏双亲委派模型

双亲委派模型,不是强制执行的一个约束,Java设计者给开发者的类加载实现方式在
Java中大部分都遵守这个模型,但是在一些应用场景,可以破坏双亲委派模型
1:在我们自定义类加载器的时候,可以复写父类ClassLoader的loadClass方法,这样就破坏了双亲委派模型了
2:程序动态性的发展,希望应用程序不用重启就可以加载最新的字节码文件,此时就需要破会模型了
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值