JAVA - 类的加载过程

JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化。

加载

加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个Class文件获取,这里既可以从ZIP包中读取(比如从jar包和war包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将JSP文件转换成对应的Class类)。

验证

这一阶段的主要目的是为了确保Class文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

准备

准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间。注意这里所说的初始值概念,比如一个类变量定义为:

public static int v = 8080;

实际上变量v在准备阶段过后的初始值为0而不是8080,将v赋值为8080的putstatic指令是程序被编译后,存放于类构造器方法之中,这里我们后面会解释。

但是注意如果声明为:

public static final int v = 8080;

在编译阶段会为v生成ConstantValue属性,在准备阶段虚拟机会根据ConstantValue属性将v赋值为8080。

解析

解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是class文件中的:

CONSTANT_Class_info

CONSTANT_Field_info

CONSTANT_Method_info

等类型的常量。

下面我们解释一下符号引用和直接引用的概念:

符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。

直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在。

初始化

初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由JVM主导。到了初始阶段,才开始真正执行类中定义的Java程序代码。

初始化阶段是执行类构造器方法的过程。方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证方法执行之前,父类的方法已经执行完毕。p.s: 如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成()方法。

注意以下几种情况不会执行类初始化:

通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。

定义对象数组,不会触发该类的初始化。

常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。

通过类名获取Class对象,不会触发类的初始化。

通过Class.forName加载指定类时,如果指定参数initialize为false时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。

通过ClassLoader默认的loadClass方法,也不会触发初始化动作。

类加载器

虚拟机设计团队把加载动作放到JVM外部实现,以便让应用程序决定如何获取所需的类,JVM提供了3种类加载器:

启动类加载器(Bootstrap ClassLoader):负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。

扩展类加载器(Extension ClassLoader):负责加载 JAVA_HOME\lib\ext 目录中的,或通过java.ext.dirs系统变量指定路径中的类库。

应用程序类加载器(Application ClassLoader):负责加载用户路径(classpath)上的类库。

JVM通过双亲委派模型进行类的加载,当然我们也可以通过继承java.lang.ClassLoader实现自定义的类加载器。

当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务都会传递到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,才会尝试执行加载任务。采用双亲委派的一个好处是比如加载位于rt.jar包中的类java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个Object对象。

JAVA - 类的加载过程的更多相关文章

  1. Java类的加载过程-重点!!

    java类的加载过程有以下几步共同完成: 加载->连接->初始化.连接又分为验证.准备.解析 一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以 ...

  2. Java类的加载过程与ClassLoader的理解及测试

    当程序准备运行某个类,但该类还未被加载到内存中时,会经过以下三个步骤进行类的加载: 类的加载(Load)→类的连接(Link)→类的初始化(Initialize) 加载:类经过javac.exe编译的 ...

  3. java类的加载过程

    1.类的加载顺序 (1)JVM在首次加载类时会对  静态初始化块.静态成员变量. 静态方法进行一次初始化. (2)只有在调用new方法时才会创建类的实例. (3)对象创建过程: 首先执行父类(如果有) ...

  4. Java 类的加载过程(阿里面试题)

    问以下程序打印出什么内容: 问题及解析如下: /** * 加载方法不等于执行方法,初始化变量则会赋值 * 类加载顺序应为 加载静态方法-初始化静态变量-执行静态代码块 * 实例化时 先加载非静态方法- ...

  5. Java类的加载、链接和初始化

    一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样 ...

  6. java类从加载、连接到初始化过程

    类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用. 每个类编译后产生一个Class对象,存储在.class文件中,JV ...

  7. java 反射,类的加载过程以及Classloader类加载器

    首先自定义一个类Person package reflection; public class Person { private String name; public int age; public ...

  8. jvm系列(一):java类的加载机制

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

  9. JVM——类的加载过程

    附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...

随机推荐

  1. 谈谈Spring中都用到了哪些设计模式?

    谈谈Spring中都用到了哪些设计模式? JDK 中用到了那些设计模式?Spring 中用到了那些设计模式?这两个问题,在面试中比较常见.我在网上搜索了一下关于 Spring 中设计模式的讲解几乎都是 ...

  2. 中小学数学卷子自动生成程序--对G同学的代码分析

    前几天,在课程要求下完成了个人项目的项目工程编写,即一个中小学数学卷子自动生成程序. 程序主要功能是用户预设账户登录后可以选择等级进行对应的小中高的数学卷子对应出题生成txt文本. 本文针对partn ...

  3. 最长非降子序列的N*logN解法

    之前讲到过求最长非降子序列的O(N^2)解法. 链接 这次在原来的基础上介绍一下N*logN解法. 该解法主要是维护一个数组minValue,minValue[i]表示最长上身子序列长度为i的数的最小 ...

  4. Python入门-第一行代码到多行代码

    不管学啥语言,开始的第一行代码都是: print("hello word") 回车之后,就代表你正式进入代码的世界! 如果报错,恭喜你获得第一个书写bug,请检查单词拼写,双引号, ...

  5. Spring-JdbcTemplate(注入到spring容器)-01

    1.导入spring-jdbc和spring-tx坐标 <dependency> <groupId>junit</groupId> <artifactId&g ...

  6. 索引优化、Sql查询语句优化

    工作中我们经常会遇到系统查询慢的情况,一般我们会采取好多方法进行优化,如建立索引,优化查询Sql,分表,规范数据表结构设计,调整数据库参数(内存分配.缓存等),增加硬件配置,优化网络环境等.下面介绍两 ...

  7. json在前后台传递的形式

    json对象和json字符串的区别纠结了好久一阵子,经过查阅大量博客资料总结得,字符串形式它就是带单引号或者双引号的,对象就是没有被引号包括,可以直接进行调用属性.前后端间数据传递json形式应该是字 ...

  8. 安卓记账本开发学习day3

    今天发现了新的错误 首先是AS警告杀毒系统对编译运行有影响,我目前只开了火绒,所以只需要在火绒里将SDK文件夹设置为信任即可 第二个错是在编译测试运行的时候,虚拟机能够正常打开,也launch suc ...

  9. Codeforces Round #671 (Div. 2) B. Stairs 难度1200

    题目链接: Problem - 1419B - Codeforces 题目 题意 给x个格子,你可以用这x个格子去拼成楼梯 好的楼梯的要求如下: 1. 第n列有n个格子 2. 这个楼梯的所有格子可以被 ...

  10. 网页跟随系统 dark mode (暗黑模式) 的实现

    经过几十年的沉默, dark mode(暗黑模式) 又回到了我们面前,越来越多的 APP 有了暗黑主题,越来月多的操作系统原生添加了 "全局暗黑模式", 那么一个网站如何跟随系统的 ...