jvm类加载机制

2018-11-22  本文已影响2人  简书徐小耳

首先举个例子
final static变量会在jvm启动的时候编译好
final 实例变量会在获取实例的时候被初始化好

class Grandpa {
    static {
        System.out.println("爷爷在静态代码块");
    }
}

class Father extends Grandpa {
    static {
        System.out.println("爸爸在静态代码块");
    }

    public static int factor = 25;

    public Father() {
        System.out.println("我是爸爸~");
    }
}

class Son extends Father {

    public static int factor2 = 25;

    static {
        System.out.println("儿子在静态代码块");
    }


    public Son() {
        System.out.println("我是儿子~");
    }
}

public class InitializationDemo {
    public static void main(String[] args) {

        System.out.println("爸爸的岁数:" + Son.factor);    //入口
    }
}
Son.factory 首先会调用父类的类构造器(<clinit>),执行静态代码快和静态方法,但是因为调用的是父类的属性factor,所以Son自己不会调用类构造器
所以这边顺序是爷爷在静态代码块,爸爸在静态代码块,factor (执行了这个)
如果我们换成System.out.println("爸爸的岁数:" + Son.factor2); ,执行结果就是,爷爷在静态代码块,爸爸在静态代码块,factor (执行了这个),factor 2,儿子在静态代码块
类加载的时机

初始化的四种情况

类加载的过程--加载,验证,准备,解析和初始化
加载
验证
准备
解析
初始化
类加载器

整个loadclass 就是按照双亲委派机制干活的
resolve=true的时候就是会去初始化类,而我们loadclass 不允许初始化类
jvm规定了四种初始化类的情况

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
        检测jvm中这个classloader和其父类中的命名空间是否已经包含该名称的class
            Class<?> c = findLoadedClass(name);
            如果没有开始按照双亲委派机制去加载类
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                首先查看父类是否存在,如果存在就调用父类的loadClass
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                    否则有可能是顶级加载器bootStrap
                        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);
                 更新下加载的耗时和次数等
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            这边至今不太理解,好像是jvm类加载的链接那一步,即验证,链接,解析
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

三种类加载器

类的加载有个默认机制 如果我们在某个类使用了 Aclassloader去加载该类,那么在该类中涉及到的其他类加载也默认使用该类

破坏双亲委派加载模式

为什么dubbo不采用jdk的spi

上一篇下一篇

猜你喜欢

热点阅读