一、类加载器是什么?
将class文件预先加载到jvm虚拟机机制。
二、JVM中存在以下三种类加载区
1、根加载器(BootStrap ,C++实现)
2、扩展加载器(Ext ,java实现)
3、系统类加载器(system,java实现)
分别有不同的作用域:
1、根加载器,加载jre之下类文件,如rt.jar出ext文件之外
2、扩展加载器,加载jre/ext之外的类文件
3、系统类加载器,加载App ClassPath指定路径下的类
三、类加载器加载模式
为了保持完整性及一致性,java的类加载机制采用了双亲委派模式进行类加载,
双亲委派模式只的是,在类加载的时候,预先使用指定加载器的父类加载器去加载class文件,当父加载器return空的时候,子加载器才进行加载
BootStrap为最高级别的加载器。
四、自定义类加载器
自定义的类加载器必须继承抽象类ClassLoader然后重写findClass方法,其实他内部还有一个loadClass方法和defineClass方法,另外两种不推荐使用,严重破坏双亲委派模型,
下面代码从网上抄下来的,一个自定义加载器的实现如下:
/**
* 一、ClassLoader加载类的顺序
* 1.调用 findLoadedClass(String) 来检查是否已经加载类。
* 2.在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。
* 3.调用 findClass(String) 方法查找类。
* 二、实现自己的类加载器
* 1.获取类的class文件的字节数组
* 2.将字节数组转换为Class类的实例
* @author lei 2011-9-1
*/
public class ClassLoaderTest {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//新建一个类加载器
MyClassLoader cl = new MyClassLoader("myClassLoader");
//加载类,得到Class对象
Class<?> clazz = cl.loadClass("classloader.Animal");
//得到类的实例
Animal animal=(Animal) clazz.newInstance();
animal.say();
}
}
class Animal{
public void say(){
System.out.println("hello world!");
}
}
class MyClassLoader extends ClassLoader {
//类加载器的名称
private String name;
//类存放的路径
private String path = "E:\\workspace\\Algorithm\\src";
MyClassLoader(String name) {
this.name = name;
}
MyClassLoader(ClassLoader parent, String name) {
super(parent);
this.name = name;
}
/**
* 重写findClass方法
*/
@Override
public Class<?> findClass(String name) {
byte[] data = loadClassData(name);
return this.defineClass(name, data, 0, data.length);
}
public byte[] loadClassData(String name) {
try {
name = name.replace(".", "//");
FileInputStream is = new FileInputStream(new File(path + name + ".class"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = 0;
while ((b = is.read()) != -1) {
baos.write(b);
}
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
上面主要记录的是java类加载器,下面记录下一个类的生命周期
类的生命周期为加载、链接(验证、准备、解析)、初始化、使用、卸载5个阶段
1、类加载,类加载就是上述所说的将类使用类加载器加载到虚拟机中
2、链接(验证、准备、解析)
验证:对装载到jvm的字节码进行验证
a、验证是否虚拟机可读字节码,验证魔数
b、验证字节码与jvm中所支持的版本是否正确,魔数后8个字节码
c、类中的方法等一些列存在是否合法,jvm对class文件的字节码有严格的规则要求
准备:准备阶段,为类中的静态变量分配内存,即放入jvm的方法区的常量池之中,需要注意的是,如果静态变量没有使用final修饰,放入方法区的值是初始值。我们在程序中定义final static int a = 100,则准备阶段中a的初值就是100。
解析:为准备阶段准备好的静态变量符号引用构建引用
3、初始化:初始化有以下4种方式
如果一个类被直接引用,就会触发类的初始化。在java中,直接引用的情况有:
通过new关键字实例化对象、读取或设置类的静态变量、调用类的静态方法。
通过反射方式执行以上三种行为。
初始化子类的时候,会触发父类的初始化。
作为程序入口直接运行时(也就是直接调用main方法)。
Java类加载器及类的生命周期与初始化过程
猜你喜欢
转载自wmhbjb.iteye.com/blog/2210185
今日推荐
周排行