类加载器基本理解

2 篇文章 0 订阅
2 篇文章 0 订阅

一、类加载器的作用

将class文件字节码内容加载到内存中,并将这些静态的数据转换成方法去中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为这个方法去中类数据的访问入口。

二、类缓存

标准的Java SE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM的垃圾回收器(GC)会回收这些class对象。

三、类加载器的层次结构

1、引导类加载器(bootstrap class loader)

1)、用来加载Java的核心库,是用原生代码(C/C++)来实现的,并不继承来自java.lang.ClassLoader类;

2)、加载扩展类和应用程序类加载器并指定他们的父类加载器。

2、扩展类加载器 (extensions class loader)

1)、用来加载Java的扩展库,Java虚拟机的实现提供了一个扩展目录。该类加载器在此目录里面查找并加载Java类。

2)、由sun.misc.Launcher$ExtClassLoader实现

3、应用程序类加载器

1)、根据Java应用的类路径(classpath,java.class.path路类)一般来说java应用的类都是由它来完成加载的。

2)、由sun.misc.LauncherLoader$AppClassLoader实现

4、自定义类加载器

可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。

四、类加载器的代理模式

1、代理模式

交给其他加载类了加载指定的类

2、双亲委托机制

1)、某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次追溯。如果父类加载器可以完成类加载的任务,就成功返回,只有父类加载器无法完成此加载任务的时候,在自己加载。

2)、双亲委托机制是为了保证Java核心库的类型安全,保证不会出现用户自己定义java.lang.Object类的情况。

3)、类加载器除了用于加载类,也是安全的最基本的屏障。

3、双亲委托机制是代理模式的一种

1)、并不是所有的类加载器都采用双亲委托机制

2)、Tomcat服务器类加载器也使用代理模式,所不同的是它首先尝试去加载这个类,如果找不到在委托给其父类加载,与一般的类加载器的顺序相反。

五、自定义类加载器

1、继承java.lang.ClassLoader类

2、首先检查请求的类型是否已经被这个类加载器加载到命名空间了,如果已加载了则直接返回,不用重新加载了。

3、委派类加载,请求父类加载,如果父类加载器能够完成,则返回父类加载器加载的class实例

4、调用本类加载器的findClass()方法,试图获取对应的字节码,如果获取的到,则调用defineClass()导入类型到方法区;如果获取不到或出现错误,则返回异常给loadClass(),抛出异常,终止加载。

package com.silence.loader;


import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;


/**
 * 自定义文件系统类加载器
 * @author zhuxiang
 *
 */
public class FileSystemClassLoader extends ClassLoader{


private String rootDir;
public FileSystemClassLoader(String rootDir){
this.rootDir = rootDir;
}


@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {


Class<?> clz = findLoadedClass(name);
//判断该类是否已经加载,如果没有则加载,反之不加载,直接返回
if (clz != null) {
return clz;
}else {
ClassLoader parent = this.getParent();
try {
clz = parent.loadClass(name);//委派给父类加载
} catch (Exception e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
if (clz != null) {
return clz;
}else {
byte[] classData = getClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
}else {
clz = defineClass(null, classData, 0,classData.length);
}
}
}
return clz;
}

private byte[] getClassData(String className){
String path = rootDir + "/" + className.replace(".", "/") + ".class";
//IOUtils可以使用它将流中的数据转换成字节数组
InputStream iStream = null;
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
try {
iStream = new FileInputStream(path);
byte[] buffer = new byte[1024];
int temp = 0;
while ((temp = iStream.read(buffer))!=-1) {
bStream.write(buffer, 0, temp);
}
return bStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}finally{
try {
iStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


}


注意:被两个类加载的同一个类,JVM不认为是相同的类,同一个类加载器加载同一个类,JVM才认为是相同的类。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值