JAVA虚拟机中是如何加载JAVA类的?


我们平时都知道通过javac命令将
.java
文件编译成
.class
文件 。之后这个class文件就可以“被运行”了 。但是我们需要搞清楚的是这个class文件在虚拟机中究竟是怎么玩的 。
要想具体搞清楚java类是如何加载的Java虚拟机中 。我们需要搞清楚以下几个问题:
一个Java类什么时候开始被加载?
加载Java类的过程是怎样的?
一个Java类从被加载到JVM内存中到这个类被卸载 。主要包含以下七个步骤的生命周期 。

JAVA虚拟机中是如何加载JAVA类的?

文章插图
一个Java类什么时候开始被加载?
Java虚拟机并没有规定在什么时候需要加载Java类 。但是对于Java类的初始化却有明确的规定 。有且只有以下5中情况时候便会立即触发类的“初始化”动作:
JAVA虚拟机中是如何加载JAVA类的?

文章插图
使用
java.lang.reflect
JAVA虚拟机中是如何加载JAVA类的?

文章插图
当初始化一个类的时候 。如果发现其父类还没有进行过初始化 。则需要先触发其父类的初始化 。这个很好理解 。就是当一个子类遇到new、getstatic、putstatic或invokestatic这4条字节码指令时 。如果父类还没有初始化 。则先初始化父类 。
当虚拟机启动时 。用户需要指定一个要执行的主类(包含main()方法的那个类) 。虚拟机会先初始化这个主类 。
当使用JDK1.7的动态语言支持时 。如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄 。并且这个方法句柄所对应的类没有进行过初始化 。则需要先触发其初始化 。这块属于动态加载的范畴 。本质上还是需要需要new、getstatic、putstatic或invokestatic这4条字节码指令 。
加载Java类的过程是怎样的?
知道了类被加载的条件后 。我们需要知道一个Java类通过怎样的过程被加载到Java虚拟机中去了 。
这个过程其实就是把一个
.class
文件中的java类相关信息加载到内存中 。通过验证、准备、解析等阶段 。最终生成一个存在于Java虚拟机内存中的
java.lang.Class
对象 。
这里面涉及到的知识点比较多:
如何验证一个
.class
文件是符合Java虚拟机规范的?
准备阶段都做哪些事情?
类加载机制是怎样的?
什么是双亲委派模型?
加载完的类存储在Java虚拟机的什么内存区域?
加载的类GC可以回收吗?如果可以回收需要满足什么样的条件才可以回收一个类?
推荐大家一定要阅读《深入理解Java虚拟机》这本Java程序员必读书籍!并且不只是读一遍 。要不停的读 。不停的品!
以上就是我个人对“JAVA虚拟机中是如何加载JAVA类的?”这个问题的一些解答 。这里只是给大家开个一个头 。需要大家再继续深耕下去 。
我是【java架构设计】 。关注我 。持续为您提供Java领域优质内容!
其他观点:
从几道面试题详细回答下这个问题
直击面试
看你简历写得熟悉JVM 。那你说说类的加载过程吧?
我们可以自定义一个String类来使用吗?
什么是类加载器 。类加载器有哪些?这些类加载器都加载哪些文件?
多线程的情况下 。类的加载为什么不会出现重复加载的情况?
什么是双亲委派机制?它有啥优势?可以打破这种机制吗?
类加载子系统
JAVA虚拟机中是如何加载JAVA类的?

文章插图
类加载机制概念
Java虚拟机把描述类的数据从Class文件加载到内存 。并对数据进行校验、转换解析和初始化 。最终形成可以被虚拟机直接使用的Java类型 。这就是虚拟机的加载机制 。Class文件由类装载器装载后 。在JVM中将形成一份描述Class结构的元信息对象 。通过该元信息对象可以获知Class的结构信息:如构造函数 。属性和方法等 。Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能,这里就是我们经常能见到的Class类 。
类加载子系统作用
类加载子系统负责从文件系统或者网络中加载class文件 。class文件在文件开头有特定的文件标识(0xCAFEBABE)
ClassLoader只负责class文件的加载 。至于它是否可以运行 。则由Execution Engine决定
加载的类信息存放于一块称为方法区的内存空间 。除了类的信息外 。方法区中还存放运行时常量池信息 。可能还包括字符串字面量和数字常量(这部分常量信息是class文件中常量池部分的内存映射)