zoukankan      html  css  js  c++  java
  • 深入研究Java类加载机制

        类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行。

        研究类加载机制的第二个目的是让程序能动态的控制类加载,比如热部署等,提高程序的灵活性和适应性。

    一、简单过程  

        Java程序运行的场所是内存,当在命令行下执行java HelloWorld命令的时候,

        JVM会将HelloWorld.class加载到内存中,并形成一个Class的对象HelloWorld.class

        其中,类加载过程如下:

        (1) 寻找jre目录,寻找jvm.dll,并初始化JVM

        (2) 产生一个Bootstrap Loader(启动类加载器)

        (3) Bootstrap Loader自动加载Extended Loader(标准扩展类加载器),并将其父Loader设为Bootstrap Loader

        (4) Bootstrap Loader自动加载AppClass Loader(系统类加载器),并将其父Loader设为Extended Loader

        (5) 最后由AppClass Loader加载HelloWorld类。 

        以上就是类加载的最一般的过程。

    二、加载明细

        类加载器各自搜索的目录:

        Bootstrap Loader(启动类加载器):加载System.getProperty("sun.boot.class.path")所指定的路径或jar

        Extended Loader(扩展类加载器ExtClassLoader):加载System.getProperty("java.ext.dirs")所指定的路径或jar。在使用Java运行程序时,也可以指定其搜索路径,

                                  例如:java -Djava.ext.dirs=d:projects estprojclasses HelloWorld

         AppClass Loader(系统类加载器AppClassLoader)加载System.getProperty("java.class.path")所指定的路径或jar。在使用Java运行程序时,也可以加上-cp来覆盖原有的Classpath设置,

                                  例如: java -cp ./lavasoft/classes HelloWorld

         ExtClassLoaderAppClassLoaderJVM启动后,会在JVM中保存一份,并且在程序运行中无法改变其搜索路径。如果想在运行时从其他搜索路径加载类,就要产生新的类加载器。

     三、类加载器的特点  

        1、运行一个程序时,总是由AppClass Loader(系统类加载器)开始加载指定的类。

        2、在加载类时,每个类加载器会将加载任务上交给其父,如果其父找不到,再由自己去加载。
        3Bootstrap Loader(启动类加载器)是最顶级的类加载器了,其父加载器为null.

    四、类加载器的获取   

     public class HelloWorld { 
            public static void main(String[] args) { 
                    HelloWorld hello = new HelloWorld(); 
                    Class c = hello.getClass(); 
                    ClassLoader loader = c.getClassLoader(); 
                    System.out.println(loader); 
                    System.out.println(loader.getParent()); 
                    System.out.println(loader.getParent().getParent()); 
            } 
        }

         打印结果:

        sun.misc.Launcher$AppClassLoader@19821f 
        sun.misc.Launcher$ExtClassLoader@addbf1 
        null 

        从上面的结果可以看出,并没有获取到ExtClassLoader的父Loader,原因是Bootstrap Loader(启动类加载器)是用C语言实现的,找不到一个确定的返回父Loader的方式,于是就返回null

      

    五、类的加载 

        类加载有三种方式:

        1、命令行启动应用时候由JVM初始化加载

        2、通过Class.forName()方法动态加载

        3、通过ClassLoader.loadClass()方法动态加载

        三种方式区别比较大,看个例子就明白了:

    public class HelloWorld { 
            public static void main(String[] args) throws ClassNotFoundException { 
                    ClassLoader loader = HelloWorld.class.getClassLoader(); 
                    System.out.println(loader); 
                    //使用ClassLoader.loadClass()来加载类,不会执行初始化块 
                    loader.loadClass("Test2"); 
                    //使用Class.forName()来加载类,默认会执行初始化块 
                     //Class.forName("Test2"); 
                    //使用Class.forName()来加载类,并指定ClassLoader,初始化时不执行静态块  
    
                 //Class.forName("Test2", false, loader); 
            } 
         }
     public class Test2 { 
            static { 
                    System.out.println("静态初始化块执行了!"); 
            } 
         } 

            分别切换加载方式,会有不同的输出结果。

    有关ClassLoader还有很重要一点:

      同一个ClassLoader加载的类文件,只有一个Class实例。

      但是,如果同一个类文件被不同的ClassLoader载入,则会有两份不同的ClassLoader实例(前提是着两个类加载器不能用相同的父类加载器)

  • 相关阅读:
    swift 第十四课 可视化view: @IBDesignable 、@IBInspectable
    swift 第十三课 GCD 的介绍和使用
    swift 第十二课 as 的使用方法
    swift 第十一课 结构体定义model类
    swift 第十课 cocopod 网络请求 Alamofire
    swift 第九课 用tableview 做一个下拉菜单Menu
    swift 第八课 CollectView的 添加 footerView 、headerView
    swift 第七课 xib 约束的优先级
    swift 第六课 scrollview xib 的使用
    swift 第五课 定义model类 和 导航栏隐藏返回标题
  • 原文地址:https://www.cnblogs.com/chy2055/p/5124064.html
Copyright © 2011-2022 走看看