java类加载过程

类加载过程

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。如图所示。
 
加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。以下陈述的内容都已HotSpot为基准。

加载

在加载阶段(可以参考java.lang.ClassLoader的loadClass()方法),虚拟机需要完成以下3件事情:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流(并没有指明要从一个Class文件中获取,可以从其他渠道,譬如:网络、动态生成、数据库等);
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;

加载阶段和连接阶段(Linking)的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。

验证

验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
验证阶段大致会完成4个阶段的检验动作:

  1. 文件格式验证:验证字节流是否符合Class文件格式的规范;例如:是否以魔术0xCAFEBABE开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型。
  2. 元数据验证:对字节码描述的信息进行语义分析(注意:对比javac编译阶段的语义分析),以保证其描述的信息符合Java语言规范的要求;例如:这个类是否有父类,除了java.lang.Object之外。
  3. 字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
  4. 符号引用验证:确保解析动作能正确执行。

验证阶段是非常重要的,但不是必须的,它对程序运行期没有影响,如果所引用的类经过反复验证,那么可以考虑采用-Xverifynone参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。

准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在堆中。其次,这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量的定义为:


1

publicstaticintvalue=123;

那变量value在准备阶段过后的初始值为0而不是123.因为这时候尚未开始执行任何java方法,而把value赋值为123的putstatic指令是程序被编译后,存放于类构造器()方法之中,所以把value赋值为123的动作将在初始化阶段才会执行。
至于“特殊情况”是指:public static final int value=123,即当类字段的字段属性是ConstantValue时,会在准备阶段初始化为指定的值,所以标注为final之后,value的值在准备阶段初始化为123而非0.

解析

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

初始化

类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在准备极端,变量已经付过一次系统要求的初始值,而在初始化阶段,则根据程序猿通过程序制定的主管计划去初始化类变量和其他资源,或者说:初始化阶段是执行类构造器<clinit>()方法的过程.

<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块static{}中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问

时间: 2024-10-18 17:42:10

java类加载过程的相关文章

java类加载过程,了解一下?

先了解一下: 什么是类的加载:jvm将class文读取到内存中,经过对class文件的校验.转换解析.初始化最终在jvm的heap和方法区分配内存形成可以被jvm直接使用的类型的过程. 生命周期:7个阶段依次为:Loading(加载)Verification (验证)Preparation (准备)Resolution(连接) Initialization (初始化)Using(使用) Unloading(卸载) 加载Loading 这个阶段jvm完成以下动作:首先  类加载器通过类的全路径限定

java类加载过程以及双亲委派机制

前言:最近两个月公司实行了996上班制,加上了熬了两个通宵上线,状态很不好,头疼.牙疼,一直没有时间和精力写博客,也害怕在这样的状态下写出来的东西出错.为了不让自己荒废学习的劲头和习惯,今天周日,也打算写一篇博客,就算是为了给自己以前立的flag(每个月必须写几篇博客)的实现.那么本次博客的主题我选择了java的类加载过程的探究以及双亲委派机制模型以及它被破坏的场景,搞清楚这个对于我们理解java的类加载过程以及面试中都是很有必要的. 本篇博客的目录 一:类加载器 二:类加载的过程和阶段 三:双

[读书笔记]Java类加载过程

一. 类的生命周期 类从被加载到虚拟机内存中开始,到卸载出内存为止,有以下(如图)的生命周期: 以上"加载->验证->准备->解析->初始化"称为类的加载过程. Java虚拟机规范中没有对什么时候需要开始类加载的第一阶段进行强制约束,而是交给了虚拟机根据具体实现来自由把握. 但是对于初始化阶段,虚拟机有以下5种必须对类立即进行"初始化"的情况: (1)遇到new.getstatic.putstatic或invokestatic这4条字节码指令

java 类加载过程

一.类加载器 1.根加载器,bootstrap,c++编写的; 2.扩展类加载器,java编写; 3.系统,应用类加载器,java编写; 4.用户自定义类加载器,java.lang.ClassLoader的子类,用户可以定制类的加载方式; 二. 类的加载方式1.本地编译好的class中直接加载2.网络加载:java.net.URLClassLoader可以加载url指定的类3.从jar.zip等等压缩文件加载类,自动解析jar文件找到class文件去加载util类4.从java源代码文件动态编译

【Java基础】java类加载过程与反射机制

1.类的加载.连接和初始化 当程序使用某个类时,如果该类还未被加载到内存中,则系统会通过加载.连接.初始化三个步骤来对类进行初始化.如果没有意外,jvm将会连续完成这三个步骤,有时也把这三个步骤统称为类的加载和类初始化. 1.1 类的加载 类加载指的是将类的class文件读入内存,并且为之创建一个java.lang.Class对象,也就是说当程序中使用任何类时,都会为之创建一个java.lang.Class对象.类的加载由类加载器完成,类加载器通常由JVM提供,这些类加载器是前面所有程序运行的基

java 类加载过程图

原文地址:https://blog.51cto.com/14437184/2438725

剑指offer-Java类加载过程

Java 类加载过程:(以A.class为例) 1. 定位A.class类,并调用findLoaderClass(string)判断这个类是否已经存在 2. 先执行父类中static成员变量与static方法块 3. 再执行子类中static成员变量与static方法块 4. 接着执行父类中非static成员变量.非static方法块和构造函数 5. 最后执行子类中非static成员变量.非static方法块和构造函数 注意:构造函数是最后执行的. 下面用测试过的代码输入来说明: (1)类中没有

深入理解Java虚拟机笔记---类加载过程

一.加载 "加载"(Loading)阶段是"类加载"(Class Loading)过程的一个阶段.在加载阶段,虚拟机需要完成以下三件事情: a.通过一个类的全限制名来获取定义此类的二进制字节流. b.将这个字节流所代表的静态存储结构转化为方法区的运行进数据结构. c.在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口. 虚拟机规范的这三点要求实际上并不具体,因此虚拟机实现与具体应用的灵活度相当大.例如"通过一

java类加载的过程

一个java文件从被加载到被卸载这个生命过程,总共要经历4哥阶段: 加载->链接(验证+准备+解析)->初始化(使用前的准备)->使用->卸载 其中加载(除了自定义加载)+链接的过程是完全由jvm负责的,什么时候要对类进行初始化工作(加载+链接在此之前已经完成了),jvm有严格的规定(四种情况): 1.遇到new,getstatic,putstatic,invokestatic这4条字节码指令时,加入类还没进行初始化,则马上对其进行初始化工作.其实就是3种情况:用new实例化一个类