一般分为:引导类加载器(bootstrap classloader)、扩展类加载器(extensions class loader)、应用程序类加载器(application class loader)、自定义类加载器 这4种类加载器
它用来加载java核心库的(java_home/jre/lib/rt.jar 或者sun.boot.class.path 路径下的内容)是用来原生代码来实现的,并不继承java.lang.classloader,是通过C++来实现。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
用来加载java的扩展(java_home/jre/ext/*.jar 或者java.ext.dirs路径下的内容)
java与虚拟机的实现会提供一个扩展库的目录,该类加载器在此目录里面查找并加载java类
由sun.misc.Launcher$ExtClassLoader实现
它根据java引用的类路径(classpath java.class.path路径
一般来说java应用的类的都是由他来来加载实现的,也就是我们经常用到的classpath路径
package classLoader;
public class ClassLoader_test {
public static void main(String[] args) {
System.out.println(ClassLoader.getSystemClassLoader());
}
}
sun.misc.Launcher$AppClassLoader@4e25154f
通过getparent()来获取相对应的父级
package classLoader;
public class ClassLoader_test {
public static void main(String[] args) {
System.out.println(ClassLoader.getSystemClassLoader());
//AppClassLoader的父类应该是ExtClassLoader
System.out.println(ClassLoader.getSystemClassLoader().getParent());
//而ExtClassLoader的父类应该是bootstrap classloader,但是它是由C++实现的,那么java中是获取不到的
System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());
}
}
sun.misc.Launcher$AppClassLoader@4e25154f
sun.misc.Launcher$ExtClassLoader@33909752
null
交给其他加载器来加载指定的类
就是给某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次追溯,直到最高的爷爷辈的,如果父类加载器可以完成类加载额任务,就成功返回;只有父类加载器无法完成的此加载任务时,自己才去加载
双亲委托机制是为了保证java核心库的类型安全
这种机制就保证不会出现用户自己能定义java.lang.Object类的情况
类加载器处理用于加载类,也是安全的最基本的保障
双亲委托机制是代理模式的一种
并不是所有的类加载器都采用双亲委托机制
tomcat服务器的类加载器也是采用代理模式,所不同的它首先尝试去加载某个类,如果找不到再代理给父类加载器,这与一般类加载器的顺序是相反的。
举个栗子
比如我突然naocan,定义了一个java.lang.String的类,那么首先是从自定义类加载器开始,先传递给AppClassLoader,然后在传递给ExtClassLoader,最后传递给BootStrapclassLoader(加载核心包的),发现存在java.lang.String,那么就会加载String类,那么就会直接返回class。这样就保证了对于外部的包进行了安全性的保障
作用:
java.lang.classLoader的类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义java类,即java.lang.Class类的一个实例
除此之外,ClassLoader还负责加载java应用所需的资源,如图像文件和配置文件
相关方法:
getParent() 返回该类加载器的父类加载器
loadClass(String name) 加载名称为name的类,返回的结果是java.lang.class类的实例
Findclass(String name) 查找名称为name的类,返回的结果是java.lang.class的类的实例
defineClass(String name,byte[] b,int off,int lent) 把字节数组b中的 内容转化为java类,返回的是
Java.lang.class的类的实例,这个方法被声明为final的
resolveClass(Class> c)链接被指定的java类
对于以上给出的方法,表示类的名称的name参数的值是类的二进制名称,需要注意的是内部类的表示,如com.example.Sample$1和com.example.Sample$inner等表示方式
package classLoader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javassist.ByteArrayClassPath;
public class FileSystemClassLoader extends ClassLoader {
private String rootDir;
//定义了文件所在的根目录
public FileSystemClassLoader(String root)
{
this.rootDir=root;
}
@Override
protected Class> findClass(String name)throws ClassNotFoundException
{
Class> class1=findLoadedClass(name);
//如果已经被加载了
if(class1!=null)
{
return class1;
}
else
{
ClassLoader parent=this.getParent();
//让父级进行加载,如果加载成功那么直接返回
try
{
class1=parent.loadClass(name);
}
catch(Exception exception)
{
exception.printStackTrace();
}
if(class1!=null)
return class1;
else
{
byte[] classData = null;
try {
classData = getClassData(name);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
if(classData==null)
throw new ClassNotFoundException();
else
{System.out.println(name+""+classData.toString()+" "+classData.length);
class1=defineClass(name, classData, 0,classData.length);
}
}
}
return class1;
}
public byte[] getClassData(String classname) throws IOException
{ String path=rootDir+"/"+classname.replace('.', '/')+".class";
System.out.println(path);
InputStream is=new FileInputStream(path);
ByteArrayOutputStream byteArrayOutputStream=null;
byte[] bs=new byte[1024];
int length=0;
try
{
byteArrayOutputStream= new ByteArrayOutputStream();
while((length=is.read(bs))!=-1)
byteArrayOutputStream.write(bs,0,length);
return byteArrayOutputStream.toByteArray();
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.println("wo是你个");
return null;
}
finally {
byteArrayOutputStream.close();
is.close();
}
}
}
package classLoader;
public class Demo3 {
public static void main(String[] args) throws ClassNotFoundException {
FileSystemClassLoader FilesystemClassLoader=new FileSystemClassLoader("d:/myjava");
Class> class1= FilesystemClassLoader.loadClass("com.bjsxt.bean.HelloWorld");
System.out.println(class1);
}
}