1.概念
类加载器是一个用来加载类文件的类。Java源代码通过javac编译器编译成类文件。然后JVM来执行类文件中的字节码来执行程序。类加载器负责加载文件系统、网络或其他来源的类文件。
2.使用类加载器获取类对象
3.查看类对象的类加载器
4.类加载器的类型
<1>应用类加载器App:加载自己写的类或者jar包下面的类<2>扩展类加载器Ext:加载jdk/jre/lib/ext/下面的所有jar包
<3>根类加载器null:加载jdk/jre/lib/jar(所有类加载器的父加载器)
首先要写一个Person实体类,以下是测试类
package com.zking.test;
import org.junit.Test;
/**
* 测试包
* 类加载器
*/
public class TestClassLoader {
/**
* 以前new一个对象
*/
@Test
public void test1(){
Person person=new Person();
person.setPname("张三");//设值
System.out.println(person.getPname());//打印
}
/**
* 通过类加载器获取对象
*/
@Test
public void test2(){
try {
//获取类对象
Class clazz=Class.forName("com.zking.entity.Person");
//通过类对象直接拿
Person per=(Person)clazz.newInstance();
per.setPname("李四");
System.out.println(per.getPname());
//获取类加载器
ClassLoader cl=clazz.getClassLoader();
//查询该类加载器的类型(应用类加载器App:加载自己写的类或者jar包下面的类App)
System.out.println(cl);//打印:sun.misc.Launcher$AppClassLoader@6b97fd
//获取 超类的 类加载器
//ClassLoader clParent=clazz.getSuperclass().getClassLoader();
//System.out.println(clParent);//打印超类:
ClassLoader clParent=cl.getParent();//扩展类加载器Ext:加载jdk/jre/lib/ext/下面的所有jar包
System.out.println(clParent);//打印:sun.misc.Launcher$ExtClassLoader@1c78e57
//
ClassLoader clGrandParent=clParent.getParent();
System.out.println(clGrandParent);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
5.自定义类加载器
package com.zking.diy;
import java.io.FileInputStream;
/**
* 自定义类加载器:自己写一个类继承人家的类,再改一改
*/
public class ClassLoaderDIY extends ClassLoader{
//重写方法:findClass+Alt+/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println("自定义类加载器");//测试语句
System.out.println(name);
name=name.replaceAll("\\.", "/");//所有的.替换成\
System.out.println("替换后:"+name);
//截取
int a=name.lastIndexOf("/");
name=name.substring(a+1);
String desktopPath="C:\\Users\\Administrator.USER-20170515AI\\Desktop\\"+name+".class";
System.out.println(desktopPath);
try {
FileInputStream fis=new FileInputStream(desktopPath);
System.out.println(fis.available());
int len=0;
byte[] b=new byte[fis.available()];
len=fis.read(b);
return defineClass(null, b, 0, len);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.zking.test;
import org.junit.Test;
import com.zking.diy.ClassLoaderDIY;
public class TestClassLoaderDIY {
@Test
public void test() throws InstantiationException, IllegalAccessException{
//使用自己的类加载器 加载对象
try {
Class clazz=Class.forName("com.zking.entity.Person", true, new ClassLoaderDIY());
System.out.println(clazz.newInstance());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
6.类加载器的工作原理:委托、可见性、单一性
委托机制
当一个类加载和初始化的时候,类仅在有需要加载的时候被加载。假设你有一个应用需要的类叫作Abc.class,首先加载这个类的请求由Application类加载器委托给它的父类加载器Extension类加载器,然后再委托给Bootstrap类加载器。Bootstrap类加载器会先看看rt.jar中有没有这个类,因为并没有这个类,所以这个请求由回到Extension类加载器,它会查看jre/lib/ext目录下有没有这个类,如果这个类被Extension类加载器找到了,那么它将被加载,而Application类加载器不会加载这个类;而如果这个类没有被Extension类加载器找到,那么再由Application类加载器从classpath中寻找。记住classpath定义的是类文件的加载目录,而PATH是定义的是可执行程序如javac,java等的执行路径。
可见性机制
根据可见性机制,子类加载器可以看到父类加载器加载的类,而反之则不行。所以下面的例子中,当Abc.class已经被Application类加载器加载过了,然后如果想要使用Extension类加载器加载这个类,将会抛出java.lang.ClassNotFoundException异常。
单一性机制
根据这个机制,父加载器加载过的类不能被子加载器加载第二次。虽然重写违反委托和单一性机制的类加载器是可能的,但这样做并不可取。你写自己的类加载器的时候应该严格遵守这三条机制。
7.网络类加载器(可以了解一下,如果有时间博主会补充上)
最后,欢迎大家来指出博主的错误之处。
本文详细介绍了Java类加载器的概念及其工作原理,包括类加载器的类型、如何使用类加载器获取类对象以及查看类对象的类加载器。此外,还讲解了自定义类加载器的方法,并探讨了类加载器的委托、可见性和单一性机制。
3702

被折叠的 条评论
为什么被折叠?



