深入研究Java虚拟机的类加载机制

说到Java虚拟机的类加载机制,很多朋友第一反应想到的应该就是ClassLoader,我也如此,不过ClassLoader其实只是Java虚拟机加载机制中的一部分,最近在看《深入理解Java虚拟机》,对Java虚拟机的类加载机制有了更深入的了解,不吐不快。

  JVM中类的整个生命周期如下:

  加载=》验证=》准备=》解析=》初始化=》使用=》卸载

  使用和卸载这两个步骤不在今天的讨论范围之内,今天我们将着重讨论一下前5个步骤,也就是JVM中类的整个加载机制。

  1、加载

  类的加载阶段,主要是获取定义此类的二进制字节流,并将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,最后在Java堆中生成一个代表这个类的java.lang.Class对象作为方法区这些数据的访问入口。

  相对于类加载过程的其他阶段,加载阶段是开发期可控性最强的阶段。我们可以通过定制不通的类加载器,也就是ClassLoader来控制二进制字节流的获取方式。

  关于ClassLoader的介绍,请参照 了解ClassLoader

  2、验证

  验证,准备和解析其实都属于连接阶段,而验证就是连接阶段的第一步。这一阶段主要是为了确保Class文件的字节流中包含的信息复合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

  主要验证过程包括:文件格式验证,元数据验证,字节码验证以及符号引用验证。

  3、准备

  准备阶段正式为类变量分配内存并设置初始值。这里的初始值并不是初始化的值,而是数据类型的默认零值。这里提到的类变量是被static修饰的变量,而不是实例变量。

  关于准备阶段为类变量设置零值的唯一例外就是当这个类变量同时也被final修饰,那么在编译时,就会直接为这个常量赋上目标值。

  4、解析

  解析时虚拟机将常量池中的符号引用替换为直接引用的过程。

  5、初始化

  在准备阶段,变量已经赋过一次系统要求的初始值,在初始化阶段,则是根据程序员通过程序的主观计划区初始化类变量和其他资源。

  Java虚拟机规范规定了有4种情况必须立即对类进行初始化(加载,验证,准备必须在此之前完成)

  1)当使用new关键字实例化对象时,当读取或者设置一个类的静态字段(被final修饰的除外)时,以及当调用一个类的静态方法时,如果类未初始化,则需先初始化。

  2)通过反射机制对类进行调用时,如果类未初始化,则需先初始化。

  3)当初始化一个类时,如果其父类未初始化,先初始化父类

  4)用户指定的执行主类(含main方法的那个类)在虚拟机启动时会先被初始化

  除了上面这4种方式,所有引用类的方式都不会触发初始化,称为被动引用。如:通过子类引用父类的静态字段,不会导致子类初始化;通过数组定义来引用类,不会触发此类的初始化;引用类的静态常量不会触发定义常量的类的初始化,因为常量在编译阶段已经被放到常量池中了。

  总结:

  在上述5个过程当中,验证,准备和解析完全由Java虚拟机主导和控制。只要加载阶段和初始化阶段程序员可以进行控制。在加载阶段可以通过实现自定义的ClassLoader来加载类的二进制流,在初始化阶段程序员则可完全按照需求来为类变量赋值。

本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-08 18:56:22

深入研究Java虚拟机的类加载机制的相关文章

JVM学习(1)——通过实例总结Java虚拟机的运行机制

JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms 逃逸分析(DoEscapeAnalysis )的概念--JVM栈上分配实验 JVM中client模式(-client)和server模式(-server)的区别 查看GC日志的方法 使用idea对JVM进行参数输入 Java栈,Java堆和方法区的交互原理 为了能让递归方法调用的次数更多一些,应该怎么做?   当今--截止本文总结之前,使用最为广泛的 JVM 为 HotSpot(HotSp

JVM学习(1)——通过实例总结Java虚拟机的运行机制(转)

俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms 逃逸分析(DoEscapeAnalysis )的概念--JVM栈上分配实验 JVM中client模式(-client)和server模式(-server)的区别 查看GC日志的方法 使用idea对JVM进行参数输入 Java栈,Java堆和方法区的交互原理 为了能让递归方法调用的次数更多一些,应该怎

深入理解Java:类加载机制及反射

一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能. 虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 2.工作机制 类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示

JVM学习笔记(三)——虚拟机类加载机制

在介绍完class文件格式后,我们来看下虚拟机是如何把一个由class文件描述的类加载到内存中的.具体来说java中类的加载涉及7个阶段:加载.校验.准备.解析.初始化.使用.卸载. 1.加载时机 并不是所有的类在程序启动时即被加载,为提升效率,虚拟机通常秉承的是按需加载的原则,即需要使用到相应的类时才加载对应的类.具体包括如下几个加载时机: 遇到new.getstatic.putstatic.invokestatic这4条指令时,如果对应的类没有被加载,虚拟机会首先加载对应的类.这4条指令对应

深入理解JVM之六:类加载机制

前言 虚拟机的类加载机制可以简单描述如下:Java虚拟机把描述类的数据从Class文件中加载到内存中,并对数据进行校验.解析和初始化,最终形成可以被虚拟机直接使用的Java类型.虚拟机加载进行类加载的过程是在程序运行期间完成的,在程序运行期间加载的好处是可以动态扩展,说白了就是在编译期间虚拟机是不知道要加载哪些类或者接口的,只有在程序运行的时候才知道需要加载的类.举个例子,我们在一个包下面写了很多类,我们在在别的包中可能只是需要其中的几个类,但是出于习惯我们可能会写成import test.*

Java虚拟机详解----JVM常见问题总结

[正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾回收.类加载机制.   先把本文的目录画一个思维导图:(图的源文件在本文末尾)   一.Java引用的四种状态: 强引用: 用的最广.我们平时写代码时,new一个Object存放在堆内存,然后用一个引用指向它,这就是强引用. 如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java

《深入理解Java虚拟机》学习笔记

自动内存管理机制 第2章 垃圾收集器与内存分配策略 1.Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域, 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在, 有些区域则是在以来用户线程的启动和结束而建立和销毁. 根据<Java虚拟机规范>,包括以下几个运行时数据区域: //此处应有类图,但是画起来太麻烦! 程序计数器(Program Counter Register) 方法区(Method Area) 虚拟机栈(VM Stack)

Java虚拟机类加载机制——案例分析

  在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬念.建议先看完<Java虚拟机类加载机制>这篇再来看这个,印象会比较深刻,如若不然,也没什么关系~~ 下面是程序代码: package jvm.classload; public class StaticTest { public static void main(String[] args) { staticFunction(); } st

Java虚拟机类加载机制

看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎么加载,博主有很长一段时间也是这么认为的.随着编程经验的日积月累,越来越感觉到了解虚拟机相关要领的重要性.闲话不多说,老规矩,先来一段代码吊吊胃口. public class SSClass{ 运行结果: SSClassSuperClass init!123 答案答对了嚒? 也许有人会疑问:为什么没有输出SubClass init.ok~解释一下:对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父