• Java 类加载机制


    类的加载:

    类的初始化:

    类什么时候才被初始化:
    1)创建类的实例,也就是new一个对象
    2)访问某个类或接口的静态变量,或者对该静态变量赋值
    3)调用类的静态方法
    4)反射(Class.forName("com.lyj.load"))
    5)初始化一个类的子类(会首先初始化子类的父类)
    6)JVM启动时标明的启动类,即文件名和类名相同的那个类
    只有这6中情况才会导致类的类的初始化。

    假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就初始化直接的父类(不适用于接口)

    加入类中存在初始化语句(如static变量和static块),那就依次执行这些初始化语句。

    类的加载:

    类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的Java.lang.Class对象,用来封装类在方法区类的对象。

    类加载器:

    import java.net.URL;
    
    public class Main {
        public static void main(String[] args) {
            URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
            for (int i = 0; i < urls.length; i++) {
                System.out.println(urls[i].toExternalForm());
            }
        }
    }
    

      

    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/lib/resources.jar
    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/lib/rt.jar
    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/lib/sunrsasign.jar
    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/lib/jsse.jar
    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/lib/jce.jar
    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/lib/charsets.jar
    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/lib/jfr.jar
    file:/D:/Program%20Files/Java/jdk1.8.0_102/jre/classes
    

      

    Java类加载机制

    类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示的对象组件。在Java中,类装载器把一个类装入JVM中,要经过以下步骤:
    (1) 装载:查找和导入Class文件;
    (2) 链接:把类的二进制数据合并到JRE中;
        (a)校验:检查载入Class文件数据的正确性;
        (b)准备:给类的静态变量分配存储空间;
        (c)解析:将符号引用转成直接引用;
    (3) 初始化:对类的静态变量,静态代码块执行初始化操作

    类加载器和双亲委派模型

    (1) Bootstrap ClassLoader : 将存放于<JAVA_HOME>lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar 名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用
    (2) Extension ClassLoader : 将<JAVA_HOME>libext目录下的,或者被java.ext.dirs系统变量所指定的路径中的所有类库加载。开发者可以直接使用扩展类加载器。
    (3) Application ClassLoader : 负责加载用户类路径(ClassPath)上所指定的类库,开发者可直接使用。

    双亲委派模型的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每个层次的类加载器都是如此。因此所有的加载请求最终都应该传达到顶层的启动类加载器中,只有当父加载器反馈无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

    双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。这些类加载器的父子关系不是以继承的关系实现,而都是使用组合关系来复用父加载器的代码。

    public class ClassLoaderTest {
        public static void main(String[] args) {
            //输出ClassLoaderText的类加载器名称
            System.out.println("ClassLoaderText类的加载器的名称:" + ClassLoaderTest.class.getClassLoader().getClass().getName());
            System.out.println("System类的加载器的名称:" + System.class.getClassLoader());
            System.out.println("ArrayList类的加载器的名称:" + ArrayList.class.getClassLoader());
    
            ClassLoader cl = ClassLoaderTest.class.getClassLoader();
            while (cl != null) {
                System.out.print(cl.getClass().getName() + "->");
                cl = cl.getParent();
            }
            System.out.println(cl);
        }
    }
    

      Output:

    ClassLoaderText类的加载器的名称:sun.misc.Launcher$AppClassLoader
    System类的加载器的名称:null
    ArrayList类的加载器的名称:null
    sun.misc.Launcher$AppClassLoader->sun.misc.Launcher$ExtClassLoader->null
    

      

    好处:java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪个类加载器要加载这个类,最终都会委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果用户自己写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,java类型体系中最基础的行为也无法保证,应用程序也会变得一片混乱。

    https://mp.weixin.qq.com/s/-Q255hbgbMIVymxceH_odw

    http://blog.csdn.net/java2000_wl/article/details/8040633

    http://blog.csdn.net/gjanyanlig/article/details/6818655

    http://www.cnblogs.com/fsjohnhuang/p/4284515.html

    http://blog.csdn.net/gjanyanlig/article/details/6818889

    http://www.cnblogs.com/ITtangtang/p/3978102.html

    http://blog.chinaunix.net/uid-21227800-id-65873.html

    http://blog.csdn.net/zhangliangzi/article/details/51338291

    转自:http://www.cnblogs.com/hongdada/p/6060487.html

  • 相关阅读:
    【开发者笔记】C#连接mysql问题记录
    【开发者笔记】揣摩Spring-ioc初探,ioc是不是单例?
    【开发者笔记】c# 调用java代码
    【数据库乱码】记录一下数据库乱码问题
    字符函数
    单行函数和多行函数
    rownum和rowid伪列
    排序子句
    单引号的转义
    逻辑运算符
  • 原文地址:https://www.cnblogs.com/panchanggui/p/9952524.html
Copyright © 2020-2023  润新知