实习杂记(30):虚拟机类的加载机制(2)

一、类加载器

什么叫  类加载器

虚拟机  把    (通过一个类的   全限定名  俩获取描述此类的  二进制字节流   )这个动作  放到java虚拟机外部去实现


以便让应用程序自己决定如何去获取所需要的类。


实现这个动作的代码  模块称为      类加载器


使用:类加载器 在类层次划分,OSGi,热部署, 代码加密  等领域大放异彩,成为java技术体系中一块重要的基石



类加载只用于  实现类的加载动作,对于任意一个类,都需要由它的类加载器  和这个类本身  一同确立  其在java虚拟机中的以  唯一性


每一个类加载器,都拥有一个独立的类名称空间


如何判断两个类是不是相同,只有在两个  类都是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那么这两个类就必定不同。


这里指的相等包括:代表类的Class对象的equals()方法,isAssignableFrom()方法,isInstance()方法返回的结果,也包括使用instanceof 关键字做对象所属关系判断等情况

import java.io.IOException;
import java.io.InputStream;

public class ClassLoaderTest {
	
	public static void main(String[] args) throws Exception{
		
		ClassLoader myLoader = new ClassLoader() {

			@Override
			public Class<?> loadClass(String name) throws ClassNotFoundException {
				try {
					String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
					
					InputStream is = getClass().getResourceAsStream(fileName);
					if (is == null) {
						return super.loadClass(name);
					}
					byte[] b = new byte[is.available()];
					is.read(b);
					return defineClass(name, b, 0, b.length);
				}catch (IOException e){
					throw new ClassNotFoundException(name);
				}
			}
			
		};
		
		Object obj = myLoader.loadClass("com.xx.classload.ClassLoaderTest").newInstance();
		System.out.println(obj.getClass());
		System.out.println(obj instanceof com.xx.classload.ClassLoaderTest);
	}
}
输出结果:

class com.xx.classload.ClassLoaderTest
false

上面的代码就是一个  类加载器,输出的结果表明  通过类加载器  实例化的类对象   和  系统应用程序类加载器加载的类对象  是不相等的

这段代表表示:这个类对象是由开发人员自己实现的类加载器

Object obj = myLoader.loadClass("com.xx.classload.ClassLoaderTest").newInstance();
这段代码instanceof操作符后面的代码,代表这个类对象是由  当前系统加载器实现的类对象
obj instanceof com.xx.classload.ClassLoaderTest

同一个Class文件,同一个虚拟机,不同的类加载器,实例化的类对象是不相等的,


二、双亲委派模型


从java虚拟机角度来看,只存在两种不同的  类加载器:

一种是           启动类加载器,这个类加载器是C++语言实现的,是虚拟机自身的一部分;这种类加载器的实例无法被

                                       用户获取。

另外一种是    所有其他类加载器,这些类加载器都是由java实现的,独立于虚拟机外部,

                                       并且全部都继承抽象类java.lang.ClassLoader


从java开发人员的角度来看,分为三种


1.启动类加载器  这个类加载器负责将存放在 <JAVA_HOME>\lib目录中,或者被-Xbootclasspath参数指定的路径中的,并且是虚拟机识别的类库加载在虚拟机中内存中,启动类加载器无法被java程序直接引用的,开发人员在编写自定义加载器的时候,如果需要把加载器请求委派给引导类加载器,那直接使用null代替即可,


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


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


如果有必要,还可以加入自己定义的  类加载器,

这些类加载器直接的关系,层级  就构成了双亲委派模型



工作过程是:如果一个   类加载器   收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子类加载器才会尝试自己去加载,


这里面的父子关系并不是通过继承来实现的,不是继承关系,而是通过组合关系来复用父类加载器的代码


双亲委派模型最大的好处就是:java类随着它的类加载器一起具备了  一种带有优先级的层次关系,例如java.lang.Object,它存放在rt.jar包中,无论哪一个类加载器都要加载这个类,最终都是委派给处于模型顶端的启动类加载器进行  加载,因此Object类在程序的各种类加载器环境中都是同一个类,


相反,如果么一双亲委派模型,由各个类自己去自行加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,java体系中最基础的行为也无法保证了,


应用程序将一片混乱,双亲模型对于保证java程序的稳定起到非常重要的作用。

三、双亲委派模型的破坏

程序中有时候仅仅依靠父类是无法完成初始化某个子类的,需要在父类中去调用子类的代码才能完成  类的加载,


这样就必然会对双亲模型造成破坏,而这种需要是肯定,但是这种破坏是褒义的,是被允许的,具体的需要去研究OSGi


每一个程序模块都已一个自己的类加载器,当需要更换一个BIndle时,就把Bindle连同类加载器一起换掉以实现代码的热替换。





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明
引用: C:\Windows\System32中cmd文件丢失,如果打开cmd,显示不存在,那么你的电脑里面的cmd.exe可执行文件丢失了,需要重新添加,打开我的电脑,搜索如下路径:C:\Windows\System32 ,将下载下来的cmd.exe文件添加到这个路径下。 引用: 设置快捷方式路径cmd.exe的文件路径是c:\windows\system32\cmd.exe。 根据你的描述,C:\Windows\System32\cmd.exe是cmd.exe的文件路径。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C:\Windows\System32 中 cmd丢失,cmd.exe 下载](https://download.csdn.net/download/weixin_40446557/10347662)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [根据cmd.exe的文件路径,30秒新建cmd快捷方式,并以管理员身份运行(保姆级图文)【杂记】](https://blog.csdn.net/u011027547/article/details/122837561)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [终端进程启动失败: shell 可执行文件“C:\Windows\System32\cmd.exe ”的路径不存在。](https://blog.csdn.net/irober/article/details/120679263)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值