java classloader_Java中ClassLoader

ClassLoader:类加载器。Java中所有的类都通过类加载器j进行加载,包含几种加载器:

BootStrapClassLoader 使用C++编写属于Java的JVM层面。用于加载核心类库(lib)下的类库

ExtensionClassLoader 用于加载Java  lib/ext下的类库

ApplicationClassLoader  也称SystemClassLoader  用于加载classPath下的类库

首先Java中类加载有五个过程:加载、验证、准备、解析、初始化。类加载器通过类全名读取类的二进制z字节流到JVM,然后转化成一个与目标类d对应的Class实例。JVM提供上面三种类加载器。一个类由不同加载器实例加载时,会在方法区产生不同类,但是彼此不可见,在堆中产生不同class实例。

ApplicationClassLoader的parent是ExtensionClassLoader,ExtensionClassLoader的parent是BootStrapClassLoader。

我们使用Java类库中的类进行获取ClassLoader:

System.out.println(String.class.getClassLoader());

System.out.println(ArrayList.class.getClassLoader());

结果:

4531ca0d18158171e54728fe845a8ed0.png

这是因为Java环境获取不到对应class,Java的类或者说jre/lib包下的类,由根加载器BootStrapClassLoader加载,环境在C++中。

我们编写任意一个类AA,使用

System.out.println(AA.class.getClassLoader());

得到如下结果:

a25a0280900385b41c0ce261e823b022.png

得到的结果是AppClassLoader也就是之前说的ApplicationClassLoader,再使用

System.out.println(AA.class.getClassLoader().getParent());

得到如下结果

11c0615d4a0a2c6ae8dd38bd25363beb.png

再使用

System.out.println(AA.class.getClassLoader().getParent().getParent());

得到的结果便是null了。因为拿不到BootStrapClassLoader

调用对象的getClass()方法是获取当前对象类的类型,该部分数据存储在方法区中,getClass().getClassLoader()方法是获取当前类型的类加载器。由于Java中所有类都通过类加载器加载到jvm中,且各个类加载器存在父子关系,子知道父的存在,父不知道子的存在,由于此不同子之间加载的类型是无法互相访问的(虽然都在方法区中),正是因为这样,通过当前类的加载器加载资源能够保证是同一个类加载器加载的。

InputStream resourceAsStream = AA.class.getClassLoader().getResourceAsStream("aa.txt");

JVM加载一个类时由BootStrapClassLoader首先进行查找加载,找不到时再有其子类ExtensionClassLoader查找加载,再找不到时由ApplicationClassLoader查找加载。这也就是“双亲委派机制”。

2.线程中的ClassLoader

每个运行中的线程都有成员ContextClassLoader线程上下文ClassLoader,用于在运行时动态加载其它类。通过

ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();

可以获取当前运行线程的上下文ClassLoader。通过

Thread.currentThread().setContextClassLoader(new ClassLoader() {

@Override

public Class> loadClass(String name) throws ClassNotFoundException {

return super.loadClass(name);

}

});

可以设置当前线程的ContextClassLoader

事实上所有Java程序都运行在线程中,若一个程序没有通过上述方法设置过ContextClassLoader,对于一般的jJava类下面两个方法获取的ClassLoader一般是同一个:

this.getClass().getClassLoader();

Thread.currentThread().getContextClassLoader();

上述两个方法区别:

第一个得到的是静态的ClassLoader,表明类的加载者

第二个得到的是动态的ClassLoader,表明当前线程。对于单例模式的类、静态的类载入一次后可能被其它多个线程调用,对于这些类,载入的ClassLoader和执行的线程的ClassLoader通常不同。

3.web应用中ClassLoader

以tomcat中webapp的ClassLoader来说,这类Class Loader与之前说过的机制略有不同,web应用线程会尝试自己加载(ContextPath/web-inf/....)中的类,若是加载不到,再请求父加载器加载。对于webapp线程,他的contextCloassloader是WebAppClassLoader,对于tomcat Server线程,他的ContextClassLoader是catalinaClassLoader。除了上述获取动态ClassLoader和获取静态ClassLoader外还可通过:

ClassLoader.getSystemClassLoader();

获取系统入口点所使用的ClassLoader。此类SystemClassLoader与根ClassLoader不同,JVM下SystemClassLoader通常为AppClassLoader。

ClassLoader可广泛用于资源载入层面,对于类资源,类可通过new,文件可进行IO。

类资源:

1.Class clazz=Class.forName("com.dabai.AA");

AA aa=(AA)clazz.newInstance():2.AA aa=newAA();3.ClassLoader cl;

Class clazz=cl.loadClass("com.dabai.AA");

AA aa=clazz.newInstance();

文件资源:

假设AA类想要读取 com/dabai/conf/  下文件conf.properties,我们可以通过绝对路径和相对路径读取,绝对路径自然是包括磁盘符的,相对路径的值是相对ClassLoader。将ClassLoader视为一棵树,相对与该ClassLoader路径后的资源都能被加载到

InputStream resourceAsStream3 = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/dabai/conf/conf.properties");

获取文件URL绝对路径:

URL resource = BB.class.getClassLoader().getResource("com/dabai/Test/conf/conf.properties");

System.out.println(resource);

a09b4f89ebb6e48038c2659df3de7ac3.png

Java中getResource()会进入到ClassLoader getResource()中,通过main方法启动时,当前ClassLoader就是AppClassLoader,其parent就是ExtensionClassLoader,再其parent就是BootStrapClassLoader。当BootStrapResource都无法找到对应资源时,就从findResource(name)中将返回值返回。

4.其它

ClassLoader的线程安全问题

类加载器需要b保证线程安全,当装载一个不存在的类时,由于双亲委派机制的存在,强制加载会报错SecurityException。

自定义类加载器的话可继承ClassLoader并重写findClass方法

c40928111f808ae604dc770d73a1aea8.png

随口一说:类加载器不加载接口,嗯。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值