1.类加载子系统

一、内存图总体

二、类加载子系统


2.1 类加载子系统三个环节:加载,链接、初始化

	补充 _反编译 指令 : javap -v xxx.class
	将 .class 文件加载到内存的三个环节: 加载 链接  初始化
	ClassLoader 只负责 加载 calss文件 ,至于能不能执行 ,由 执行引擎 决定 

2.1.1 第一个环节 :Loading 阶段(加载)

	1.通过 一个类 的全限定名 获取此类的 二进制字节流 
	2.将 
	3.在内存中 生成 一个 大的 Class 类的 对象 ,作为类的访问入口 

2.1.2 第二个环节 :Linking 阶段(链接)

链接阶段 分为 三个阶段 : 验证(Verify)、准备(Prepare) 、解析(Resolve)
		验证: 验证是不是 class文件 , 二进制开头:CA FE BA BE(咖啡baby)
		准备:为变量分配内存,以及设置默认值 ,即 0,null,false,/u000(char)
				final编译的时候就分配值了,准备阶段 显示初始化(确定一下)
				这里不会为 new 的对象分配内存,因为 还在 加载 类 的阶段
		解析:将常量池的 符号引用 转为 直接引用 (未了解)(动态链接相关)

2.1.3 第三个环节: Initialization 阶段(初始化)

		初始化阶段就是 执行 类构造器方法<client>()方法和<Init>()方法
		<client>():
			javac 编译器 自动收集 类中 的 所有 全局变量(static、类变量)和 静态代码块 的赋值动作 而来
			按照顺序执行 赋值的 (是 赋值 ,声明 已经在 第二个环节(Linking的 准备环节)已经声明过 了)

			<Init>():
			执行构造器,一定是 先执行父类 在执行子类的 
			子类被加载之前,一定是先加载 父类
			如下图, 输出语句用到了 SON 首先会 加载 SON的父类 然后加载子类

2.2 类的加载器分类

		类加载器分类:
			1.引导类加载器(BootStrap ClassLoader)   		C和C++(可多继承)实现的
			2.拓展类加载器(Ext ClassLoader)				java实现的
			3.系统类加载器(App(System) ClassLoader))		java实现的
			
			引导类加载器 负责 加载java的核心类库 JDK,出于安全的考虑,引导类加载器只加载包名为:java、javax、sun开头的
			拓展类加载器 负责 加载 jre\lib\ext 子目录的类库,如果用户创建的 jar包放进去,那么,拓展类加载器 也会 加载 用户的 jar包
			系统类加载器 负责 用户自定义类
2.2 后续 、拓展:用户自定义类加载器
			为什么要自定义要类加载器:
				1.隔离 加载类( 类名啥的 都相同,需要隔离)
				2.修改类的加载方式()
				3.扩展加载源()
				4.防止源码泄露(很容易被篡改,可以对字节码以 自己 的方式进行加密,执行解密需要 自定义类加载器 解密)
				
			怎么做:
				1.extend ClassLoader 
				2.1.2之前 ,需要重写一个 loadclass()方法 
				  1.2之后,建议把自定义的逻辑卸载 findClass()方法中,不需要重写loadClass()了
				3.如果没有太过于复杂的要求,可以直接继承URLClassLoader,使代码更简洁

2.3 双亲委派机制

	先不加载,先让父亲去加载,递归,直到引导类,
	如果 引导类加载器 能完成加载任务,那就加载,不会向下委托了。
	如果不能完成加载任务,然后 再向下 委托,直到 能完成任务。
	
	某些接口由 引导类加载的,那么 实现类 由 系统类(第三层) 加载器 加载的
	
	优势:
		1.避免类的重复加载
		2.保证程序的安全,防止核心类库被篡改( 沙箱安全机制 ) , 防止自己的类和核心类库jdk冲突
	判断JVM中两个类是否为同一个类:
		1.包名和类名一样
		2.加载此类的ClassLoader必须是一样的	

posted @ 2021-07-04 18:03  宋佳强  阅读(75)  评论(0编辑  收藏  举报