类加载机制

67 阅读2分钟

Java运行时编译源码(.java)成字节码(.class)由jre运行。jre由Java虚拟机实现。JVM分析字节码。解释并运行。

JVM类加载器

  • Bootstrap classLoader:主要负责加载核心类库。
  • ExtClassLoader:主要负责加载jre/lib/ext目录下可扩展jar。
  • AppClassLoader:主要负责加载应用程序主函数。

类加载机制

  • 全盘负责委托机制:当一个ClassLoader加载一个类的时候,除非显示的使用另一个ClassLoader,该类所依赖和引用的类也由这个ClassLoader载入。
  • 双亲委派机制:当一个类收到类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委托给父类去完成,每一个层次类加载都是如此,因此所有的类加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),自类加载器才会尝试自己去加载。

双亲委派机制

沙箱安全机制:比如自己写的String.class类不会被加载,这样可以防止核心库被随意篡改。

避免类的重复加载:当父ClassLoader已经加载类的时候,就不需要子ClassLoader再加载一次。

ClassLoader loadClass方法

public Class<?> loadClass(String name) throws ClassNotFoundException {
    return loadClass(name, false);
}    
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) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            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;
    }
}

双亲委派机制

类加载生命周期

  • 加载:将class文件从磁盘加载到内存。

  • 链接。

    • 验证:验证字节码文件的正确性。
    • 准备:给类的静态变量分配内存,并赋予默认值。
    • 解析:类加载器装入类所引用的其他类。
  • 初始化:为类的静态变量赋予正确的初始值,执行静态代码块。

  • 使用。