1. 类加载器有两种(下面说的父类并不是继承关系,而是包装关系):
1.1. Java虚拟机自带的类加载器:
1.1.1. 根类加载器(Bootstrap) --> C++编写
1.1.1.1. 该加载器没有父加载器,它负责加载虚拟机核心类库,如java.lang.*等。
1.1.2. 扩展类加载器(Extension)--> java编写
1.1.2.1. 它的父类加载器是根类加载器,它从java.ext.dirs系统属性所指定的目录加载类库,或从JDK的安装目录 jre/lib/ext子目录下加载类库
1.1.2.2. 如果把用户创建的jar文件放在这个目录下也会由扩展类加载器加载
1.1.2.3. 它是java.lang.ClassLoader的子类
1.1.3. 系统类加载器(System)--> java编写
1.1.3.1. 也称之为应用类加载器(AppClassLoader),父类加载器为扩展类加载器。
1.1.3.2. 它从环境变量classpath或者系统java.class.path所指定的目录加载类
1.1.3.3. 它是用户自定义类加载器的默认父加载器
1.1.3.4. 它是java.lang.ClassLoader的子类
1.2. 用户自定义类加载器
1.2.1. java.lang.ClassLoader(抽象类)的子类
1.2.2. 通过继承ClassLoader,复写findClass(String name)方法来自定义类的加载方式
2. 如何获取某一个类的类加载器?getClassLoader()方法
通过use null to represent the bootstrap class loader就能明白,获取类加载器返回为空的时候,说明类的类加载器就是根类加载器
package com.odao; public class Student { public static void main(String[] args) throws ClassNotFoundException { Class clazz = Class.forName("java.lang.String"); System.out.println(clazz.getClassLoader()); Class clazz1 = Class.forName("com.odao.Student"); System.out.println(clazz1.getClassLoader()); } } clazz.getClassLoader()返回为:null 说明String类是由根类加载器加载的 clazz1.getClassLoader()返回为:sun.misc.Launcher$AppClassLoader@43be2d65(应用类加载器) 说明Student类的类加载器为系统加载器
3. 父类委托机制
JDK1.2版本开始,类的加载过程采用父亲委托机制,这种机制能更好地保证Java平台的安全。
在此委托机制中,除了Java虚拟机自带的根类加载器以外,其余的类加载器有切仅有一个父加载器
例如:当Java程序请求加载器loader1加载Sample类时,loader1首先委托自己的父加载器去加载Sample,父加载器能加载Sample,则由父加载器加载,否则才由加载器loader1本身加载Sample类
为什么都先要判断父类加载器能否加载?
假如我们自己构造了一个有风险的类(不符合Jvm规范的),然后自定义了一个类加载器来加载这个有风险的类,那么是不是就会给程序带来不安全的因素。