• JVM学习二:JVM之类加载器之加载分析


    前面一遍,我们对类的加载有了一个整体的认识,而这一节我们细节分析一下类加载器的第一步,即:加载。

                                                 

    一、概念

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

    加载.class文件的方式:
      1.从本地系统中直接加载
      2.通过网络下载.class文件
      3.从zip,jar等归档文件中加载.class文件
      4.从专有数据库中提取.class文件
      5.将Java源文件动态编译为.class文件

    类的加载的最终产品是位于堆区中的Class对象。
    Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

    二、加载器分类

    类的加载器有两种:
    1、Java虚拟机自带的加载器
    2、用户自定义类加载器
    而Java虚拟机自带的加载器又包括3种类加载器:
    1.根类加载器(Bootstrap)
    2.扩展类加载器(Extension)
    3.系统类加载器(Ststem)
    系统类加载器又称为应用类加载器
    其中扩展类加载器和系统类加载器是使用Java实现的。而根加载器是使用C++实现的,JVM的API也没有暴露根类加载器,程序员无法在Java代码中获取根加载器。用户自定义类加载器是用户自己写的类加载器,但是必须继承java.lang.ClassLoader这个类,用户可以自定义类的加载方式!
    我们先来看下类加载器的相关API

     

    每个Class对象都包含了一个对定义的Classloader的定义,也就是说通过Class我们可以拿到对应的Classloader,那我们再来看一下Class这个对象如何拿到Classloader。

    Class对象有一个getClassLoader的方法用于返回该类的类加载器,但有些实现可能使用null来标识引导类加载器(根类加载器)。也就是说当我们使用根加载器加载的对象使用此方法获取到的ClassLoader是null,为什么是这样呢?前面我们也已经说了,根类加载器是使用C++编写的,JVM不能够也不允许程序员获取该类,所以返回的是null,下面还有一句,如果此对象表示的是一个基本类型或void,则返回null,其实进一步的含义就是:Java中所有的基本数据类型都是由根加载器加载的!(JDK1.5以后将void纳入为基本数据类型)!

    下面我们通过代码来具体来看一下类的相关加载器!(看下面一段代码)

    public class ClassLoaderTest {
    
    
        public static void main(String[] args) throws ClassNotFoundException {
    
           System.out.println(Class.forName("java.lang.String").getClassLoader());
    
        }
    
    }

    刚才我们已经说了,基本数据类型使用根类加载器加载的,因此本类中java.lang.String获取类加载器返回的结果应该是null。运行结果如下:

    查看自定义的类加载器:

    public class ClassLoaderTest {
    
        public static void main(String[] args) throws ClassNotFoundException {
    
        System.out.println(Class.forName("com.jvm.classloader.test.ClassLoaderTest").getClassLoader());
    
        }
    
    }

    我们可以看到运行结果是AppClassLoader执行的,即应用类加载器(系统类加载器)! 那么什么时候加载,即加载时机是?

    三、加载时机

    通过上面我们了解了类加载器之加载,也知道了其分类,那么到底什么时候加载呢?

    类的加载时机:所有的类或接口都是在Java虚拟机首次“主动使用”的时候才会初始化(初始化章节分析),类从class文件到内存经过了“加载”、“连接”、“初始化”,类是在首次主动使用的时候进行初始化,那他是什么时候加载的呢?

    类的加载并不需要到该类或接口被首次主动使用的时候才加载,JVM规范允许类加载器在预料到某个类将要被使用时就预先加载它,如果在预先加载工程中遇到了.class文件缺失或存在错误,则类加载器必须在程序主动使用该类的时候报告LinkageError错误,如果这个类一直没有被程序主动使用,则该类加载器不会报告错误!即使不存在这个类也不会报告错误!

    参考资料:

     圣思园张龙老师深入Java虚拟机系列

  • 相关阅读:
    20145228 《信息安全系统设计基础》第九周学习总结 (1)
    20145228《信息安全系统设计基础》期中总结
    20145228《信息安全系统设计基础》第一次实验实验报告
    20145228 《信息安全系统设计基础》第八周学习总结 (1)
    20145228 《信息安全系统设计基础》第七周学习总结 (2)
    20145228 《信息安全系统设计基础》第七周学习总结 (1)
    20145228 《信息安全系统设计基础》第六周学习总结 (2)
    20145228 《信息安全系统设计基础》第六周学习总结 (1)
    20145203《信息安全系统设计》 实验二 固件开发
    20145203 《信息安全系统设计基础》第九周学习总结
  • 原文地址:https://www.cnblogs.com/pony1223/p/8641015.html
Copyright © 2020-2023  润新知