当前位置: 首页 >> 面试题 >> 技术 >> 后端开发 >> Java >>

JVM如何加载.class文件的?

ClassLoader就是类加载器,是Java中的核心组件。类加载器主要工作在类加载中的加载过程,它所负责的任务就是,根据类的全限定名获取定义该类的二进制字节流,这个获取方法在虚拟机规范并没有要求,既可以从jar包,war包中读取,也可以从网络中获取,或者是由JSP文件生成。类加载器将该字节流转化为具体的类对象,存放在JVM的方法区中,作为该类的访问入口。

除此之外,ClassLoader还与两个类的“相等”有关。两个类相等的其中一个必要条件就是加载它们的类加载器一定要是同一个,换句话来说,即使两个类出自同一个class文件,如果是经过不同的类加载进行加载,在JVM中也不是相等的两个类。所以这也正是双亲委派模型的一个重要意义。

从开发者角度来看,ClassLoader有四种:

  • 启动类加载器 BootStrapClassLoader:它是所有类加载器的祖先,也就是双亲委派模型下的顶层。它的责任是负责加载<JAVA_HOME>/lib目录下的核心类库,比如说像Object,System这样的类都是由启动类加载器来进行加载的。并且,它是根据文件名来判断合法性的,也就是说,即使我们将一个不符合规范的类库放进目录里,也是不会被加载的。那启动类加载器是由JVM中的C++来实现的,所以在Java语言中是无法直接调用的。
  • 扩展类加载器 :在双亲委派模型下,它是启动类加载器的子加载器,而在Java中,它的父加载器显示为null,没错,正是因为启动类加载器是C++实现的,所以在Java中理所应当是null。它所负责的就是加载<JAVA_HOME>/lib/ext目录下的class文件或者jar包。并且是由Java实现的,所以可以在Java中进行调用。我们也可以把自己实现的jar包放在对应的目录下让扩展类加载器进行加载,实现对核心类库的扩展。
  • 应用类加载器:主要负责加载ClassPath下也就是工程目录下的class文件和jar包。所以我们平时写的自定义类默认都是通过应用类加载器来进行加载的。
  • 自定义类加载器:除了使用默认的这三种,我们还可以自定义类加载器。一般的做法就是继承ClassLoader抽象类,然后重写findClass方法,在里面加载好对应的字节数组,然后作为参数传给defineClass方法,完成真正的类加载。

Loading