视频: https://www.bilibili.com/video/av29502877
1 JVM把Class加载到内存当中,检验解析初始化。默认使用的懒加载方式。
以下步骤是并行执行
可以把加载源看成JAVA配置文件。
解析:
符号引用: 类名,基本类型
直接引用:内存地址
初始化:
1 类初始化是线程安全的,多个线程同时触发类初始化时,只有一个类可以执行,其他类阻塞
2 类初始化时执行<clinit>方法,<clinit>按照书写顺序加载并执行类的static代码。
自上而下,由父到子。自加载器将加载任务上抛,直到顶层。父类加载器加载失败抛出异常,把加载任务转给子类加载器。
这样可以防止重复加载。比如:自定义一个java.lang.Object类,加载时先放到顶层父加载器中,发现已经加载过jdk的java.lang.Object类。此时就不会在加载自定义Object。
下面是java中类加载双亲委派的源码
java.lang.ClassLoader#loadClass(java.lang.String, boolean)
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 检查全类名是否已经加载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 statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}