在jDK1.8中,Classloader加载class的字节码到JVM,它是遵循双亲委派模型的加载机制,主要是由BootstrapClassLoader,ExtClassLoader、AppClassloader,然后是自定义的Classloader加载,这样做主要是保证JDK的内部类加载安全性,所以优先加载JDK的ClassPath的jar包的类.双亲委派模型的如下图所示,其实就是由两级父Classloader加载,分别是BootstrapClassloader和ExtClassloader。
JDK的双亲委派模型
以下是Classloader的loadClass的和核心代码:
- 首先获取class的name的锁,是为了防止多线程并发的加载一个类,只有一个线程去加载,
- findLoadedClass获取JVM已经加载的缓存中该Classloader实例是否已经加载该类, JVM底层实际是SystemDictionary,其底层是HASH表实现。
- 如果JVM的缓存没有加载过这个className,则先交给parent加载器加载,
如果parent为空,则由BootstrapClassloader去加载,由于BootstrapClassloader是由C++实现,java没有这个类,所以通过JNI调用JVM的函数去加载。 4. 如果还没有加载到,则子类实现的findClass方法去加载。 5. 最后判断resolve参数,是否处理class的链接。 6. 最后返回class,没有加载到,由子类抛出ClassNotFoundException异常.
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();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFound