类加载器小结

作者: 雅俗共赏M | 来源:发表于2017-04-07 18:45 被阅读42次

    最近遇到了一些问题,然后就了解了一些类加载的过程。在学习过程中,发现类加载器在其中起到了很大的作用,今天就把前几天看的类加载器的东西给稍作总结一下吧.

    目录:

    1. 什么是类加载器
    2. 类加载器的常用方法
    3. 类加载器结构
    4. 类加载器的加载机制
    5. 类被初始化的时机(扩展)
    6. 相关知识

    1.什么是类加载器

    A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a "class file" of that name from a file system. --- Oracle official document

    We know that Java Program runs on Java Virtual Machine (JVM). When we compile a Java Class, it transforms it in the form of bytecode that is platform and machine independent compiled program and store it as a .class file. After that when we try to use a Class, Java ClassLoader loads that class into memory. ---http://www.journaldev.com

    顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。 ---IBM中文论坛社区

    从上边的各种解释中可以简单总结出:类加载器就是把class文件加载到虚拟机,或者说是内存中。

    2. 类加载器的常用方法

    loadClass(String name);
    findClass(String name);
    defineClass(String name, byte[] b, int off, int len);
    getParaent();
    

    3. 类加载器结构

    3.1 类加载器包括哪些:

    • 引导类加载器 (负责加载核心库 由c++实现)
    • 扩展类加载器 (负责扩展库 由c++实现)
    • 系统类加载器 (负责加载CLASSPATH)
    • 继承ClassLoader实现自定义类加载器

    3.2 类加载器的树状组织结构:

    类加载器的树状组织结构

    4. 类加载器的加载机制

    结合3.2给出的那副树状组织结构图,来说一下类加载器的加载机制:代理模式/双亲委派机制

    什么是代理模式呢?
    某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

    这样做的目的是什么?
    这样做的目的是防止内存中出现多份同样的字节码,还可以保证java核心库的安全(因为不同的类加载器实例加载相同的类,它们的类型也不一致)

    下边附上一段代码来测试虽然是同一个类,但是由不同的类加载器加载之后,它们的类型也是不一样的。

        public void testClassIdentity() {
            String classDataRootPath = "C:\\workspace\\Classloader\\classData";
            FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath);
            FileSystemClassLoader fscl2 = new FileSystemClassLoader(classDataRootPath);
            String className = "com.example.Sample";
            try {
                Class<?> class1 = fscl1.loadClass(className);
                Object obj1 = class1.newInstance();
                Class<?> class2 = fscl2.loadClass(className);
                Object obj2 = class2.newInstance();
                Method setSampleMethod = class1.getMethod("setSample", java.lang.Object.class);
                setSampleMethod.invoke(obj1, obj2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    5. 类被初始化的时机(扩展)

    • 类被初始化的时机(扩展)
    • 访问类的静态变量(访问final常量不会触发初始化)
    • 访问类的静态方法
    • 反射
    • 当初始化一个类时,发现其父类还未初始化,则先出发父类的初始化
    • 虚拟机启动时,定义了main()方法的那个类先初始化

    6. 相关知识

    有关类初始化的面试题1
    有关类初始化的面试题2

    参考文章:

    Java ClassLoader
    深入探讨 Java 类加载器
    类加载器官方文档

    相关文章

      网友评论

        本文标题:类加载器小结

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