java加载class文件(类加载机制)

来源:互联网 发布:市场营销模拟平台软件 编辑:程序博客网 时间:2024/05/16 10:43

一概述:在编译期,所有的*.java文件被编译成.class文件。在运行期,class文件只有被加载到jvm内存中才能运行。这个装载工作是由类装载器完成的。实质就是把class文件从硬盘读取到内存中,并对数据进行校验,转化解析和初始化,最终形成可以被jvm直接使用的java类型。


二类加载全过程


                                                                                            类的生命周期

1、加载

  1)通过一个类的全限定名来获取定义此类的的二进制字节流

  2)将这个字节流所代表的静态存储结构转化为方法区运行时的数据结构

  3)在内存中生成一个java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

2、 验证:确保Class文件中的字节流中的包含信息符合jvm的要求,并且不会虚拟机自身的安全。

3、准备:在方法区给静态的类变量分配内存,并设置初始值。实例变量(未被static修饰的类变量)将会在对象实例化时,随对象一起分配到java堆中。

4、解析:将符号引用转成直接引用。其中解析阶段可以在初始化后再开始,这是为了支持JAVA语言运行时绑定(动态绑定或晚绑定,例如多态)。

5、初始化:对静态变量和静态代码块执行初始化工作。


三类加载时机

  1、 jvm规范并没有强制约束类加载过程的第一个阶段,具体实现由jvm自由把握。但是有且只有5种情况必须对类进行初始化(而加载、验证、准备自然需要在此之前开始)。这里简单说说最常见的java代码场景是:使用new关键字实例化对象的时候,读取或设置类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。

  2、类加载的动态性体现

  一个应用程序是由n多个类组成的。Java程序启动时,先把基础的类加载到jvm,其他类等到需要用时,再加载到jvm。这样做的好处主要是为了节省内存的开销;而用时再加载也是java动态性的一种体现。


四类加载器是如何协调,加载类的

1、类分为三种:系统类,扩展类,应用类(程序员自定义的类)。

2、类装载器:本质上也是一种类。层次结构如下,

  Bootstrap classloader  - 负责加载系统类
            |
          - - ExtClassLoader  - 负责加载扩展类
                    |
                   - - AppClassLoader  - 负责加载应用类

bootstrap classloader是由c++写的,所以逻辑上不存在bootstrap classloader的类实体,当用getParent()打印输出bootstrap classloader,结果为null。

3、加载流程:当运行一个程序,jvm启动,运行bootstrap classloader,该ClassLoader加载java核心API,然后调用ExtClassLoader加载扩展API,最后APPClassLoader加载Classpath目录下定义的Class,这就是一个程序最基本的加载流程。类的加载过程使用了一种父类委托模式。当尝试加载一个类时,会先检查这个类是否已经加载。如果没有加载,先获取父类装载器搜索路径进行装载,如果parent找不到或parent不存在,就依照自己的装载器进行加载类。采取这种模式的原因有两个。1当父类已经加载了该类的时候,就没有必要子类ClassLoader再加载一次;2如果不使用父类委托模式,那么可以随时使用自定义的String来动态代替Java核心API中定义的类型,存在非常大的安全隐患。下面是ClassLoader中的一段代码,

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{       synchronized (getClassLoadingLock(name)){           //首先检查该name指定的class是否被加载过           Class c = findLoadedClass(name);           if (c == null) {               try {                   if (parent != null) {                       //如果parent不为null,则调用parent的loadClass进行加载                       c = parent.loadClass(name, false);                   } else {                       //如果parent为null,则调用bootstrap ClassLoader进行加载                       c = findBootstrapClassOrNull(name);                   }               }catch (ClassNotFoundException e) {                     // ClassNotFoundException thrown if class not found                     // from the non-null parent class loader               }               if (c == null) {                   // If still not found, then invoke findClass in order                   // to find the class.                   //如果仍然无法加载成功,则调用自身的findClass进行加载                   c = findClass(name);                }            //带解析装入类            if (resolve) {               resolveClass(c);            }            return c;           }      }}

0 0
原创粉丝点击