2-JVM-类加载

作者: 宠辱不惊的咸鱼 | 来源:发表于2018-01-27 23:51 被阅读3次

    加载过程

    • 装载load
      • 查找并加载类的二进制数据
    • 链接link
      • 验证
        • 确保被加载类的正确性和合法性,防止高手伪造恶意的非法class文件
      • 准备
        • 为类的静态变量分配内存,并将其初始化为默认值
      • 解析
        • 符号引用 - 直接引用
    • 初始化initialize
      • 为类的静态变量赋予正确的初始值
      • 静态代码块

    初始化

    • 引起类初始化情况
      • 称为主动引用,被动引用不会引发初始化
      • new一个对象,new字节码指令
      • 访问类或接口的静态变量,或对类静态变量赋值,getstatic,putstatic(final修饰,编译期已进入常量池的除外)
      • 调用类的静态方法,invokestatic
      • 反射调用,如Class.forName("类全限定名")
      • 初始化子类前,会先初始化父类
      • JVM启动时标明的启动类
    • 初始化步骤
      • 若未装载和链接,则先装载和链接
      • 假设存在直接父类且直接父类还未初始化,则初始化直接父类(接口呢???)
      • 依次执行初始化语句(static变量和static语句块)

    说明

    • 类加载的最终产物是位于堆区(还是方法区???)中的Class对象,Class对象封装了类在方法区内的数据结构,向程序员提供了访问方法区内数据结构的接口
    • 加载源
      • 本地文件系统
      • 通过网络下载class文件
      • 从zip和jar等归档文件中加载
      • 专有数据库中提取
      • 动态编译java源文件

    类加载器

    • 架构
      • Bootstrap ClassLoader
        • JRE/lib/rt.jar
        • -Xbootclasspath指定的jar包
        • C++写的
      • Extention ClassLoader
        • JRE/lib/ext/*.jar
        • -Djava.ext.dirs指定目录下的jar包
      • App ClassLoader(System ClassLoader)
        • classpath
        • -Djava.class.path所指定目录下的类和jar包
      • Custom ClassLoader(User Defined Classloaders)
        • 继承java.lang.ClassLoader,自定义类加载器
    • 双亲委派
      • 检查类是否已被加载:自底向上
      • 加载类:自顶向下

    Faster Class Loading

    • A feature called Class Data Sharing (CDS) was introduce in HotSpot JMV from version 5.0. During the installation process of the JVM the installer loads a set of key JVM classes, such as rt.jar, into a memory-mapped shared archive. CDS reduces the time it takes to load these classes improving JVM start-up speed and allows these classes to be shared between different instances of the JVM reducing the memory footprint.

    Classloader Reference

    • All classes that are loaded contain a reference to the classloader that loaded them. In turn the classloader also contains a reference to all classes that it has loaded.

    相关源码

    # Class
    public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement
    
    @CallerSensitive
    public static Class<?> forName(String className) throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }
    
    private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller) throws ClassNotFoundException;
    
    # ClassLoader
    public abstract class ClassLoader
    
    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);//这个方法在ClassLoader里没有实现,而是简单的抛出异常,可以看下javassist.Loader中的实现)
                    // 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;
        }
    }
    

    相关文章

      网友评论

        本文标题:2-JVM-类加载

        本文链接:https://www.haomeiwen.com/subject/qkooaxtx.html