JVM面试题详解系列——类加载过程详解-创新互联

什么时Java的类加载机制

Java 虚拟机一般使用 Java 类的流程为:首先将开发者编写的 Java 源代码(.java文件)编译成 Java 字节码(.class文件),然后类加载器会读取这个 .class 文件,并转换成 java.lang.Class 的实例。有了该 Class 实例后,Java 虚拟机可以利用 newInstance 之类的方法创建其真正对象了。

创新互联建站自2013年创立以来,是专业互联网技术服务公司,拥有项目网站建设、成都网站设计网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元西湖做网站,已为上家服务,为西湖各地企业和个人服务,联系电话:18982081108

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

类的生命周期

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载7个阶段。其中验证、准备、解析3个部分统称为连接。
在这里插入图片描述

类加载过程

Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢?

系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。

加载

类加载的第一个阶段,在这个阶段,虚拟机主要完成以下3件事:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流。
  2. 将字节流中所代表的静态数据结构转化为方法区的运行时数据结构。
  3. 在内存中生成一个代表该类的java.lang.Class对象,作为方法去中这个类各种数据的访问入口。
验证

连接阶段的第一步,该阶段主要目的是为了确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。从整体上看,这个阶段大致会完成下面四个阶段的检验动作:文件格式验证、元数据验证、字节码验证和符号引用验证。

在这里插入图片描述

准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些类变量所使用的内存都将在方法区中分配。

对于该阶段,需要注意以下几点:

  1. 这个阶段进行内存分配的仅包括类变量( Class Variables ,即静态变量,被 static 关键字修饰的变量,只与类相关,因此被称为类变量),而不包括实例变量。实例变量会在对象实例化时随对着象一起分配在Java堆中。
  2. 从概念上讲,类变量所使用的内存都应当在方法区中进行分配。
    在JDK 1.7 之前,HotSpot 使用永久代来实现方法区的时候,实现是完全符合这种逻辑概念的。 而在 JDK 1.7 及之后,HotSpot 已经把原本放在永久代的字符串常量池、静态变量等移动到堆中,这个时候类变量则会随着 Class 对象一起存放在 Java 堆中。
    具体细节请移步观看我的另一篇博客——JVM面试题详解系列——JVM内存区域详解。
  3. 这里所设置的初始值通常情况下是数据类型默认的零值(如 0、0L、null、false 等),比如我们定义了public static int test = 6 ,那么 test 变量在准备阶段的初始值就是 0 而不是 6(初始化阶段才会赋值)。特殊情况:如果给 test 变量加上了 final 关键字public static final int test = 6 ,那么准备阶段 test 的值就被赋值为 6。
解析

解析阶段是虚拟机将常量池中的符号引用替换为直接引用的过程。解析动作主要针对接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符这7类符号应用进行。

在程序执行方法时,系统需要明确知道这个方法所在的位置。Java 虚拟机为每个类都准备了一张方法表来存放类中所有的方法。当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法了。通过解析操作符号引用就可以直接转变为目标方法在类中方法表的位置,从而使得方法可以被调用。

综上,解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。

符号引用

符号引用是一组用来描述所引用目标的符号,属于编译原理方面的概念,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。

直接引用

直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。直接引用可以帮助程序直接定位到所需的对象。

符号引用和直接引用的详细介绍请移步观看我的另一篇博客——JVM面试题详解系列——Java中几种常量池的区分。

初始化

初始化阶段是执行类构造器()方法的过程,是类加载的最后一步,到了这一步,Java虚拟机才开始真正执行类中定义的 Java 程序代码(字节码)。在准备阶段,类变量已经赋过一次系统要求的初始零值,而在初始化阶段,则会根据程序员通过程序制定的主观计划去初始化类变量和其他资源。需要注意的是,() 不是程序员在 Java 代码中直接编写的方法,而是由 Javac 编译器自动生成的。

卸载

卸载类即该类的 Class 对象被 GC。

卸载类需要满足 3 个要求:

  1. 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。
  2. 加载该类的ClassLoader已经被回收。
  3. 该类对应的Java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享文章:JVM面试题详解系列——类加载过程详解-创新互联
文章网址:http://azwzsj.com/article/cdscei.html