【转】深入理解java虚拟机---类加载器

2017-06-05  本文已影响16人  王帅199207

转自:http://blog.csdn.net/a707854407/article/details/40684255

类加载器是一个用来加载类文件的一个类.Java源代码通过javac编译器编译成类文件.然后jvm来执行类文件中的字节码来执行程序.
类加载文件负责加载文件系统、网络或其他来源的类文件.
有以下三种默认使用的类加载器:

类加载器的工作原理

类加载器的工作原理基于三个机制:委托、可见性和单一性.

public class TestClassLoader {
    public static void main(String[] args) {
        System.out.println("ClassLoader.getClass().getClassLoader():" + TestClassLoader.class.getClassLoader());
        
        try {
            Class.forName("test.TestClassLoader",true,TestClassLoader.class.getClassLoader().getParent());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

当你自定义一个类加载器时你应该遵守上面三条

类加载的时机:类从被加载到虚拟机内存中开始.到卸载出内存为止.它的整个生命周期包括为:加载、验证、准备、解析、初始化、使用和卸载7个阶段.其中验证、准备、解析是三个部分统称为连接.

发生顺序

其中类加载的过程中包括了加载、验证、准备、解析、初始化五个阶段.在这个五个阶段中.加载、验证、准备和初始化这四个阶段发生的顺序是确定的.而解析阶段不一定.它在某些情况可以在初始化阶段之后开始.这是为了支持java语言的运行时绑定(也称为动态绑定或晚期绑定).另外注意这里的几个阶段是按顺序开始.但不是按顺序进行或完成.因为这些阶段通常都是互相交叉地混合进行的.通常在一个阶段执行的过程中调用或激活另一个阶段.

静态绑定:即前期绑定.在程序执行前方法已经被绑定.此时由编译器或其他连接程序实现.针对java、简单的可以理解为程序编译期的绑定.java当中的方法只有final、static、private和构造方法是前期绑定的.动态绑定:即晚期绑定.也叫运行时绑定.在运行时根据具体对象的类型进行绑定.在java中.几乎所有的方法都是后期绑定.

类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远远不限于类的加载阶段。对于任意一个类,都需要由它的类加载器和这个类本身一同确定其在就Java虚拟机中的唯一性,也就是说,即使两个类来源于同一个Class文件,只要加载它们的类加载器不同,那这两个类就必定不相等。这里的“相等”包括了代表类的Class对象的equals()、isAssignableFrom()、isInstance()等方法的返回结果,也包括了使用instanceof关键字对对象所属关系的判定结果。

例如:类构造器<client>()方法的测试

package test;

public class DeadLoopClass {
    static
    {
        try {
            System.out.println("DeadLoopClass init");
            Thread.sleep(10000);
            System.out.println("DeadLoopClass over");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        System.out.println(holyshit.value);
        
    }
}


class holyshit
{
    public static int value = 123;
    static
    {
        try {
            System.out.println("holyshit init");
            Thread.sleep(10000);
            System.out.println("holyshit over");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

同时也明白.一般未使用到的类不会调用类构造器<client>()的方法(也就是"static{}").如果main方法调用到了那个类的变量或实例化了那个类才会调用.

例如:实例化类<init>()方法的测试

public class fuck {
    static
    {
        try {
            Thread.sleep(10000);
            System.out.println("执行完");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        fuck f = new fuck();
        fuck f2 = new fuck();
    }
}
上一篇 下一篇

猜你喜欢

热点阅读