Java 虚拟机程序员IT@程序员猿媛

【Java 虚拟机笔记】类加载机制相关整理

2019-03-12  本文已影响42人  58bc06151329

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

1. 概述

类的生命周期

2. 类的加载过程

2.1 加载(Loading)

2.1.1 类加载器

类加载器

双亲委派模型

java.lang.ClassLoader

//加载指定名称(包括包名)的二进制类型,供用户调用的接口
public Class<?> loadClass(String name);
//加载指定名称(包括包名)的二进制类型,同时指定是否解析(但是,这里的resolve参数不一定真正能达到解析的效果),供继承用
protected synchronized Class<?> loadClass(String name, boolean resolve);
protected Class<?> findClass(String name)
//定义类型,一般在findClass方法中读取到对应字节码后调用,可以看出不可继承(说明:JVM已经实现了对应的具体功能,解析对应的字节码,产生对应的内部数据结构放置到方法区,所以无需覆写,直接调用就可以了)
protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError{}
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;
    }
}

OSGi

2.2 校验(Verification)

2.3 准备(Preparation)

数据类型 零值
int 0
long 0L
short (short) 0
char '\u0000'
byte (byte) 0
boolean false
float 0.0f
double 0.0d
reference null
public static int value = 1;
public static final int value=1;

2.4 解析(Resolution)

2.5 初始化(Initialization)


public class Test
{
    static
    {
        i = 0;                          //给变量赋值可以正常编译通过。
        System.out.println(i);          //这句编译器会提示:Cannot reference a field before it is defined(非法向前引用)。
    }
    static int i = 1;
}
public class Test {

    static class Parent {
        public static int A = 1;

        static {
            A = 2;
        }
    }

    static class Sub extends Parent {
        public static int B = A;
    }

    public static void main(String[] args) {
        System.out.println(Sub.B);
    }

}
/*print 
2
*/
public class Test {

    static class DeadLoopClass {
        static {
            if (true) {
                System.out.println(Thread.currentThread() + "init DeadLoopClass.");
                while (true) {

                }
            }
        }
    }

    public static void main(String[] args) {
        Runnable script = new Runnable() {
            @Override public void run() {
                System.out.println(Thread.currentThread() + "start.");
                DeadLoopClass dlc = new DeadLoopClass();
                System.out.println(Thread.currentThread() + "run over.");
            }
        };

        Thread thread1 = new Thread(script);
        Thread thread2 = new Thread(script);
        thread1.start();
        thread2.start();
    }

}
/*print
Thread[Thread-0,5,main]start.
Thread[Thread-1,5,main]start.
Thread[Thread-0,5,main]init DeadLoopClass.
*/
public class Test {

    static class DeadLoopClass {
        static {
            if (true) {
                System.out.println(Thread.currentThread() + "init DeadLoopClass.");
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Runnable script = new Runnable() {
            @Override public void run() {
                System.out.println(Thread.currentThread() + "start.");
                DeadLoopClass dlc = new DeadLoopClass();
                System.out.println(Thread.currentThread() + "run over.");
            }
        };

        Thread thread1 = new Thread(script);
        Thread thread2 = new Thread(script);
        thread1.start();
        thread2.start();
    }

}
/*print
Thread[Thread-0,5,main]start.
Thread[Thread-1,5,main]start.
Thread[Thread-0,5,main]init DeadLoopClass.
Thread[Thread-0,5,main]run over.
Thread[Thread-1,5,main]run over.
*/

对类进行初始化的时机

不进行初始化情况

public class Test {

    static class Parent {
        public static int A = 1;

        static {
            System.out.println("ParentClass init.");
        }
    }

    static class Sub extends Parent {
        static {
            System.out.println("SubClass init.");
        }
    }

    public static void main(String[] args) {
        System.out.println(Sub.A);
    }

}
/*print
ParentClass init.
1
*/
public class Test {

    static class DeadLoopClass {
        static {
            if (true) {
                System.out.println(Thread.currentThread() + "init DeadLoopClass.");
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        DeadLoopClass dlc = new DeadLoopClass();
    }

}
/*print
Thread[main,5,main]init DeadLoopClass.
*/
public class Test {

    static class DeadLoopClass {
        static {
            if (true) {
                System.out.println(Thread.currentThread() + "init DeadLoopClass.");
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        DeadLoopClass[] dlcs = new DeadLoopClass[10];
    }

}
/*print
*/
public class Test {

    static class DeadLoopClass {
        static {
            if (true) {
                System.out.println(Thread.currentThread() + "init DeadLoopClass.");
            }
        }

        public static final int A = 1;
    }

    public static void main(String[] args) {
        System.out.println(DeadLoopClass.A);
    }

}
/*print
1
*/

init 和 clinit 区别

static{} 静态代码块与 {} 普通代码块异同点

参考资料

https://blog.csdn.net/w760079528/article/details/77845267
https://blog.csdn.net/shengmingqijiquan/article/details/77508471
http://www.cnblogs.com/ygj0930/p/6536048.html
https://www.cnblogs.com/ITtangtang/p/3978102.html
https://blog.csdn.net/noaman_wgs/article/details/74489549
http://www.importnew.com/18548.html

上一篇 下一篇

猜你喜欢

热点阅读