Java虚拟机(三)类加载器详细介绍

本文详述了Java虚拟机中的类加载器,包括类加载器的职责、双亲委派模型的工作原理及其实现,以及类加载器的分类,如Bootstrap、ExtClassLoader和AppClassLoader。通过实例展示了类加载器如何影响类的唯一性,并阐述了自定义类加载器的实现。
摘要由CSDN通过智能技术生成

大家好,我是一个爱举铁的程序员Shr

 

本篇文章将详细介绍类加载器,阅读完本篇文章你可能需要20分钟。

 

今天讲述的内容包括:类和类加载器之间的关系,类加载器的分类,类加载器的双亲委派模型。

 

一、什么是类加载器?

类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为类加载器[1]

 

上一篇文章类加载机制中讲的是Java虚拟机如何加载Class文件,而类加载器就是实现“如何加载”的程序代码。

 

二、类和类加载器

类加载器只实现类的加载动作,而类在虚拟机中还会有链接,初始化等阶段,详细阶段请查看前一篇文章Java虚拟机(二)类加载机制

 

对于一个类,都会由这个类本身和加载这个类的类加载器共同确认它在Java虚拟机中的唯一性。

 

举一个例子,一个类被不同的类加载器加载会发生什么。

 

新建一个Hello类,这个类将作为被不同类加载器加载的类。

package com.shrmus.classloader;

public class Hello {

}


新建一个自定义类加载器,继承java.lang.ClassLoader抽象类,重写findClass方法。

package com.shrmus.classloader;

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

public class MyClassLoader extends ClassLoader{
	@Override
	protected Class<?> findClass(String name){
		byte[] bs = null;
		try {
			String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
			InputStream inputStream = getClass().getResourceAsStream(fileName);
			if(inputStream == null) {
				return super.loadClass(name);
			}
			bs = new byte[inputStream.available()];
			inputStream.read(bs);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return defineClass(name, bs, 0, bs.length);
	}
}

新建一个Main类。

package com.shrmus.classloader;

public class Main {
	public static void main(String[] args) throws Exception {
		MyClassLoader myClassLoader = new MyClassLoader();
		Object newInstance = myClassLoader.findClass("com.shrmus.classloader.Hello").newInstance();
		System.out.println(newInstance.getClass().getClassLoader());
		System.out.println(newInstance instanceof com.shrmus.classloader.Hello);
		
		Hello hello = new com.shrmus.classloader.Hello();
		System.out.println(hello.getClass().getClassLoader());
		System.out.println(hello instanceof com.shrmus.classloader.Hello);
	}
}

控制台打印结果:

com.shrmus.classloader.MyClassLoader@33909752

false

sun.misc.Launcher$AppClassLoader@6d06d69c

true

 

Main类中,用自定义的类加载器加载Hello类并生成实例。

 

然后第一行打印的是新生成的实例的类加载器。

 

第二行打印语句通过instanceof关键字来看新生成的实例是否还属于原来的类型,控制台打印的是false

 

然后再用new关键字生成一个实例,第三行打印的是这个对象的类加载器,可以看到和第一行打印出来的类加载不一样。

 

第四行打印的是true

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值