1、类加载器
(1)书写代码:
public static void main(String[] args) {
ClassLoader classLoade=Test1.class.getClassLoader();
System.out.println(classLoade);
}
sun.misc.Launcher$AppClassLoader@18b4aac2
(2)查看源码(sun.misc.Launcher):
public Launcher() {
Launcher.ExtClassLoader var1;
try {
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
执行代码:
public static void main(String[] args) {
ClassLoader classLoade=Test1.class.getClassLoader();
while(classLoade!=null){
System.out.println(classLoade.getParent());
}
}
sun.misc.Launcher$ExtClassLoader@1b6d3586
所以,AppClassLoader的父类是ExtClassLoader,
(3)查看源码(ClassLoader):
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
锁保证了同时只能有一个可以LoadClass,同时保证了唯一性,首先检查是否被加载过了,如加载过了则直接返回(c!=null)。
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
ExtClassLoader的父类是Bootstrap
启动(Bootstrap)类加载器:用来加载java核心类库,无法被java程序直接引用。负责将JAVAHOME/lib下面的类库加载到内存中(比如rt,jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
标准扩展(Extension)类加载器:它用来加载Java的扩展库。Java虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载Java类。负责将JAVA_HOME/jre/lib/ext或者由系统变量java.ext.dirs指定位置中的类库加载到内存中
应用程序(Application)类加载器:它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。由于这个类加载器是ClassLoader中的getSystemClassLoader)方法的返回值,因此一般称为系统(System)加载器
加载顺序:自顶向下
检测顺序:自底向上
(4)双亲委任机制
当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。
目的:安全
父类能加载的就不给子类加载
程序安全是JDK的事,文件安全是系统的事
程序员写了不安全的程序,JDK有责任不让它运行
(5)其它
判断两个对象是不是同一个对象:使用的是不是同一个类加载器