Java类加载机制

简单来说,java类加载有以下几个过程:

   加载->验证->准备->解析->初始化->使用->卸载

一、加载:

  ·  通过类的全限定名获取其自定义二进制流

  ·  将二进制流所代表的静态数据结构转化为方法区的运行时数据结构

  ·  在堆中生成一个class对象,作为方法区访问这些数据的数据入口

   类加载器:

       ·引导类加载器

                负责将 <JAVA_HOME>/lib路径下的核心类库或-Xbootclasspath参数指定的路径下的jar包加载到内存中(出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类)

       ·扩展类加载器

                 Launcher的静态内部类,负责加载<JAVA_HOME>/lib/ext目录下或者由系统变量-Djava.ext.dir指定位路径中的类库

       ·系统类加载器

               它负责加载系统类路径java -classpath或-D java.class.path 指定路径下的类库

    双亲委派机制:

          如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载

         优势:

             ·可以避免类的重复加载

            ·可以防止核心API库被随意篡改

    类加载器之间关系:

            ·启动类加载器由c++实现,没有父类加载器

            ·拓展类加载器(ExtClassLoader)父类加载器是null

            ·系统类加载器(AppClassLoader)父类加载器是ExtClassLoader

            ·任何自定义加载器父加载器是AppClassLoader

    JVM中判断两个类class对象是否是一个对象:

            ·类的完整包名必须一致

            ·加载这个类的classLoader实例对象必须一致

             这是因为不同的classLoader拥有不同的独立的类名空间,所以加载的class也会在不同的类名空间中。

    Class文件的显式、隐式加载:

            ·显式加载:Class.forName()或者直接显式加载class对象

            ·隐式加载:如在加载某个类的class文件时,该类的class文件中引用了另外一个类的对象,此时额外引用的类将通过JVM自动加载到内存中。

验证:

      主要就是确保被加载类的正确性

       ·  文件格式验证:验证.class字节流是否符合class文件的格式规范,是否能被当前虚拟机处理,主要对魔数、版本号、常量池等验证

       ·  元数据验证:主要进行语义分析,判断这个类所描述的信息是否满足java语言的对应规范。类似于是否有父类,类中的方法字段是否冲突

       ·  字节码验证:确定语义是否合法,主要验证方法是否会对虚拟机造成伤害。

       ·  符号引用验证:主要是发生在将符号转化为直接引用的时候。对类自身以外的信息进行校验,确保能够解析成功。

准备:

     主要是在方法区中为类变量分配内存并设置初始值

     ·  类变量

     ·  类成员变量(在初始化阶段进行分配内存)

            Static修饰的变量将在准备阶段被分配内存,并进行初始化

            private static int i = 5;        

            这句代码在准备阶段 i 的值是0;但是若是加上final那么就是5

解析:

       JVM 针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符 7 类引用进行解析。这个阶段的主要任务是将其在常量池中的符号引用替换成直接其在内存中的直接引用。

初始化:

       用户定义的代码真正开始,虚拟机会根据语句执行顺序对类对象进行初始化,一般jvm遇到下面五种情况会触发初始化:

               ·  遇到new、getstatic、putstatic、invokestatic字节码指令时,如果没有初始化,那么会触发初始化(访问类的静态变量、静态变量的赋值、调用类的静态方法)

              ·  使用反射反射类时,如果没有进行过初始化,那么就进行初始化

              ·  初始化一个类时,如果父类没有进行初始化,那么就进行初始化

              ·  虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先初始化这个类

              ·  当使用 JDK1.7 动态语言支持时,如果一个 java.lang.invoke.MethodHandle实例最后的解析结果

               REF_getstatic,REF_putstatic,REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。

使用:

      当 JVM 完成初始化阶段之后,JVM 便开始从入口方法开始执行用户的程序代码。这个阶段也只是了解一下就可以。

卸载:

      当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值