走进JVM之"类加载过程"

我们都知道任何程序都需要加载到内存才能与CPU进行交流

字节码.class文件同样需要加载到内存中, 才可以实例化类, 兵马未动粮草先行, ClassLoader正是准备粮草的先行军, 它的使命就是提前加载.class类文件到内存中, 在类加载时, 使用的是Parents Delegation Model, 称为: 双亲委派模型

java的类加载是一个运行时核心基础设施模块, 主要是在启动时进行类的Load, Link和Init, 即为加载, 链接, 初始化

  • 第一步, 加载(Load)阶段读取类文件产生二进制流, 并转化为特定的数据结构, 初步校验常量池, 文件长度,
    是否有父类等,然后创建对应类的java.lang.Class实列

  • 第二步, 链接(Link)阶段包括验证, 准备, 解析三个步骤, 验证是更详细的校验, 比如final是否合规, 类型是否正确,
    静态变量是否合理等, 准备阶段是为静态变量分配内存, 并设定默认值, 解析类和方法确保类与类之间的相互引用正确性,完成内存结构布局

  • 第三步, 初始化(Init)阶段执行类构造器方法, 如果赋值运算是通过其他类的静态方法来完成的,
    那么会马上解析另外一个类, 在虚拟机栈中执行完毕后通过返回值进行赋值

java类加载过程如图:
在这里插入图片描述

理解: 将.java源文件编译成字节码, 然后进行类加载(类加载又分为三步加载, 链接, 初始化, 链接又分为三步: 验证, 准备, 解析), 加载完之后,或者直接解释执行, 让CUP读取, 或者让JIT编译之后转为机器码再让CUP读取

类加载是一个将.class字节码文件实列化成Class对象并进行相关初始化的过程, 在这个过程中, JVM会初始化继承树上还没有被初始化过的所有父类, 并且会执行这个链路上所有未执行过的静态代码块, 静态变量赋值语句等, 某些类在使用时, 也可以按需有类加载器进行加载

全小写的class是关键字, 用来定义类, 而首字母大写的Class, 它是class的类

  • Class类下的newInstance()在JDK9中已经置为过时,
    使用getDeclaredConstructor().newInstance()的方式, new与newInstance的区别,
    new是强类型校验, 可以调用任何构造方法, 在使用new操作的时候, 这个类可以没有被加载过,
    而Class类下的newInstance是弱类型, 只能调用无参构造方法, 如果没有默认构造方法,
    就抛出InstantiationException异常
    , 如果此构造方法没有权限访问,
    则抛出IllegalAccessException异常
    , java通过类加载器把类的实现与类的定义进行解耦, 所以是实现面向接口编程,依赖倒置的必然选择

private成员在类外是否可以修改?
答: 可以的, 通过setAccessible(true)操作, 即可以使用大写Class类的set方法修改其值

如下代码:

public class Test{
		private static Class<Two> two = Two.class;
		
		public static void main(String[] args) throws Exception{
		
			//通过newInstance方法创建Two对象
			Two twoObject = two.newInstance();
			
			//通过two这个大写的Class对象, 获取私有成员属性对象Field
			Field privateFieldInTwo = two.getDeclaredField("inner");

			//设置私有对象可以访问和修改
			privateFieldInTwo.setAccessible(true);
		
			//修改私有对象的值
			privateFieldInTwo.set(twoObject,"Hello Word");
		}
}

class Two{
	private String inner="time flies";

	public String getInner(){
		return inner;
	}

}

类加载器类似于原始部落结构, 存在权利等级制度, 最高的一层是家族中威望最高的Bootstrap, 它是在JVM启动时创建的, 通常由与操作系统相关的本地代码实现, 是最根基的类加载器, 负责装载最核心的java类, 比如Object, System, String等

第二层是在JDK9版本中, 称为Platform ClassLoader, 即平台类加载器, 用以加载一些扩展的系统类, 比如XML, 加密, 压缩相关的功能类等, JDK9之前的加载器是Extension ClassLoader,

第三层是Application ClassLoader的应用类加载器, 主要是加载用户定义的CLASSPATH路径下的类, 第二, 三层类加载器为java语言实现, 用户也可以自定义类加载器

类加载器具有等级制度, 但是并非继承关系, 低层次的当前类加载器, 不能覆盖更高层次类加载器已经加载的类

用户在什么情况下需要自定义类加载器?
答:
(1), 隔离加载类
(2), 修改类加载方式
(3), 扩展加载源
(4), 防止源码泄漏

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值