一、什么是类的加载?
答:java时分两步的,编译和运行,类的加载指的是将编译生成的类的class文件读入内存,并为之创建一个java.lang.Class对象。类的加载过程是由类加载器来完成,而类加载器由JVM提供。
二、类的加载器有哪些?
1.Bootstrap ClassLoader:负责加载%JAVA_HOME%/jre/lib下的jar包,或者说jdk的本地jar包,比如rt.jar解压后中就包含了我们常用的java类的class文件
2.Extension ClassLoader:负责加载%JAVA_HOME%/jre/ext或者java.ext.dirs系统熟悉指定的目录的jar包,或者说jdk中内部实现的扩展类
3.System ClassLoader:自定义加载器的父类,负责加载ClassPath下的类文件(程序中的类文件)
三、什么是双亲委派机制?
1.目的:为了防止内存中存在多份同样的字节码(安全),他不会尝试自己加载类,而是把请求委托给父加载器去完成,依次向上
2.解释:只有当父加载器在自己搜索范围内找不到特定的类时(即ClassNotFoundException), 子加载器才会尝试自己去加载
3.举例:String.class进行加载时,他会从下至上依次委托,直到Bootstrap ClassLoader为止,这就保证了最基础的类始终由Bootstrap ClassLoader进行加载。如果没有这个机制,我们就可以当“坏人”,自定义加载器去加载多份String.class文件
四、如何自定义类加载器和ClassLoader源码解析
1.自定义类加载器只需要定义一个类继承ClassLoader即可
public class ykClassLoader extends ClassLoader{
//1.如果你想要简单的自定义加载的话则重写findClass方法
//2.如果你想要破坏双亲委派机制的话则重写loadClass方法
}
2.ClassLoader核心方法LoadClass
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 1.从缓存里查看是否已加载
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// 2.判断父加载器是否为null,并进行对应的处理
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
// 3.如果前面的都没有找到,则调用findClass方法进行加载
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。