zoukankan      html  css  js  c++  java
  • 类的加载器

    ### 类的加载器

    1. java类的加载器种类有哪些

    1. 根类加载器---->C++编写的,无法查看源码
    2. 扩展类加载器---->加载位置:jrelibext中
    3. 系统(应用)类加载器----->加载位置:classpath中
    4. 自定义类加载器----->继承ClassLoader

    2. 类什么时候被初始化?

    1. 创建类的实例,也就是new一个对象
    2. 访问某个类或者接口的静态变量,或者对该静态变量进行赋值
    3. 调用类的静态方法
    4. 反射(Class.forName("完全限定名"))
    5. 初始化一个子类(首先会初始化子类的父类)
    6. JVM启动时表明的启动类,即文件名与类名相同的那个类

    3. 类的初始化步骤

    1. 如果这个类还没有被加载或者链接,那先进行加载和链接
    2. 假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就直接初始化父类(不适用于接口)
    3. 假如类中存在初始化语句(如static变量和static块),那就依次执行这些初始化语句

    4. java类加载体系之ClassLoader双亲委托机制

    1. java是一种类型安全的语言,它有四类称为沙箱安全机制的安全机制来保证语言的安全性,这四类安全沙箱分别是:

    1. 类加载体系
    2. .class文件检验器
    3. 内置java虚拟机的安全特性
    4. 安全管理及java API

    2. java程序中的.java文件编译完成会生成.class文件,而.class文件就是就是通过被称为类加载器的ClassLoader加载的,而ClassLoader在加载过程中会使用'双亲委派机制'来加载class文件

    1. BootStrapClassLoader:启动类加载器,该ClassLoader是JVM在启动时创建的,用于加载$JAVA_HOME$/jre/lib下面的类库。由于启动类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不能通过引用直接操作

    2. ExtClassLoader:扩展类加载器,该ClassLoader是在sun.misc.launcher里作为一个内部类ExtClassLoader定义的(即sun.misc.Launcher$ExtClassLoader),ExtClassLoader会加载$JAVA_HOME$/jre/lib/ext下的类库

    3. AppClassLoader:应用程序类加载器,该加载器同样在sun.misc.Launcher里面作为一个内部类AppClassLoader定义(即sun.misc.Launcher$AppClassLoader),AppClassLoader会加载java环境变量ClassPath所指定的路径下的类库,而ClassPath所指定的路径可以通过System.getProperty("java.class.path")获取;该变量也可以覆盖,可以使用参数-cp,例如:java -cp路径

    4. CustomClassLoader:自定义类加载器,该ClassLoader是指我们自定义的ClassLoader,比如tomcat的StandardClassLoader属于这一类;当然大部分情况下使用AppClassLoader就足够了

    5. 前面谈到了ClassLoader的几类加载器,而ClassLoader使用双亲委派机制来加载class文件。ClassLoader的双亲委派机制是这样的(这里先忽略掉自定义类加载器)

    1. 当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成

    2. 当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成

    3. 如果BootSrapeLoader加载失败(例如在$JAVA_HOME$/jre/lib里未查到该class),会使用ExtClassLoader来尝试加载

    4. 若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException

    5. 下面是ClassLoader的loadClass(String name,boolean resolve)的源码:

    ```java
    protected Synchronized Class<?> loadClass(String name,boolean resolve) throws ClassNotFoundException{
    //首先找缓存是否有class
    Class c=findLoadedClass(name);
    if(c==null){
    //判断有没有父类
    try{
    if(parent!=null){
    //有,用父类递归获取class
    c=parent.loadClass(name,fasle);
    }else{
    //没有父类。通过一下方法来加载
    c=findBootstrapClassOrNull(name);
    }
    }catch(ClassNotFoundException e){
    //ClassNotFoundException thrown if class not found
    //form the non-null parent class loader
    }
    if(c==null){
    //如果还是没有找到,调用findClass(name)去找这个类
    c=findClass(name);
    }
    }
    if(resolve){
    resolveClass(c);
    }
    return c;
    }
    ```

    首先找缓存(findLoaderClass),没有的话就判断有没有parent,如果有就使用parent来递归的loadClass,然而ExtClassLoader并没有配置parent,则会通过findBootstrapClassOrNull来加载class,而findBootstrapClassOrNull则会使用JNI方法“private native Class findBootstrapClass(String name)”来使用BootStrapClassLoader来加载class;如果parent没有找到class,则会调用findClass来加载class,findClass是一个protected的空方法,可以覆盖t它以便自定义class加载过程。另外,虽然ClassLoader加载类是使用classLoader方法,但是鼓励用ClassLoader的子类重写findClass(String),而不是重写classLoader,这样就不会覆盖了类加载默认的双亲委派机制。

    5. 双亲委派为什么安全?

    1. 例如:ClassLoader加载的class文件来源很多,比如编译器生成的class或者网络下载的字节码。而一些来源的class文件时不可靠的,比如可以自定义一个java.lang.Integer类覆盖JDK中默认的Integer类

    ```java
    package java.lang;
    public class Integer{
    public Integer(int value){}
    System.exit(0);
    }
    ```

    初始化这个类的构造器是会退出JVM,破坏应用程序的正常进行,如果使用双亲委派机制的话该Integer永远不会被调用,以为委托BootStrapClassLoader加载后会加载JDK中Integer类而不会加载自定义的这个,可以看看下面这个测试用例:

    ```java
    poblic static void main(String[]args){
    Integer i=new Integer(1);
    System.err.println(i);

    }
    ```

    执行时并未在new Integer(1)时退出,说明未使用自定义的Integer,于是就保证了安全性

  • 相关阅读:
    phpcms列表页内容如何替换?
    如何用phpcms将静态网页生成动态网页?
    简单介绍phpcms以及phpcms如何安装?
    注册账号的验证
    js跳转页面
    流程审核处理
    关于XML(可扩展标记语言)的基础知识与写法
    php随机获取验证码
    流程管理
    HDU 5894 hannnnah_j’s Biological Test
  • 原文地址:https://www.cnblogs.com/juddy/p/14329283.html
Copyright © 2011-2022 走看看