Java 引用类型

Java 中的引用类型细分为四种:类,接口,数组类和泛型参数。

因为泛型参数会在编译过程中被擦除,所以 Java 虚拟机实际上只有前三种。数组类是由 Java 虚拟机直接生成的,其他两种则有对应的字节流。

无论是数组类还是其他两种类型,Java 虚拟机都需要对其进行链接和初始化。

加载

加载就是查找字节流,然后据此创建类的过程。数组类由 Java 虚拟机直接生成,其他类则需要 Java 虚拟机借助类加载器来完成查找字节流的过程。

类加载器有很多种,除了启动类加载器以外,其他的类加载器都是 java.lang.ClassLoader 的子类,因此有对应的 Java 对象。这些类加载器都需要先由其他类加载器比如说启动类加载器加载到 Java 虚拟机中,方能执行类加载。

双亲委派机制:每当一个类加载器接收到加载请求时,它会先将请求转发给父类加载器。如果父类加载器没有找到所请求的类的情况下,该类加载器才会尝试去加载。

在 Java 9 之前,启动类加载器负责加载最基础最重要的类。除了启动类加载器之外,还有扩展类加载器和应用类加载器,均由 Java 核心类库提供。

扩展类加载器的父类加载器是启动类加载器。它负责加载相对次要但通用的类。

应用类加载器的父类加载器是扩展类加载器。它负责加载应用程序路径下的类。

Java 9 中扩展类加载器被改名为平台类加载器。Java SE 中除了少数几个关键模块是由启动类加载器加载之外,其他模块均由平台类加载器所加载。

在 Java 虚拟机中,类的唯一性是由类加载器实例以及类的全名一同确定的。

链接

链接是指将创建成的类合并至 Java 虚拟机中,使之能够执行的过程。它可以分为:验证,准备和解析三个阶段。

验证阶段:确保加载类能够满足 Java 虚拟机的约束条件。通常情况下,Java 编译器生成的类文件必然满足 Java 虚拟机的约束条件。(除了字节码注入)

准备阶段:为被加载类的静态字段分配内存,初始化则会在初始化阶段进行。部分 Java 虚拟机还会在此阶段构造其他跟类层次相关的数据结构,比如说用来实现虚方法的动态绑定的方法表。

在 class 文件被加载至 Java 虚拟机之前,这个类无法知道其他类以及其方法和字段所对应的具体地址,甚至不知道自己方法和字段的地址。当需要引用这些成员时,Java 编译器会生成一个符号引用,在运行阶段这些符号引用会定位到具体目标上。

解析阶段就是将这些符号引用解析成为实际引用。

Java 虚拟机规定:如果某些字节码使用了符号引用,那么在执行这些字节码之前,需要完成对这些符号引用的解析。也就是说,在链接过程中不要求一定解析完成。

初始化

在 Java 代码中,初始化一个静态字段,可以声明时赋值,也可以在静态代码块中赋值。

如果被赋值的静态字段被 final 修饰,并且它是基本类型或者字符串时,那么该字段便会被 Java 编译器标记成常量值,其初始化直接由 Java 虚拟机完成。除此之外的直接复制操作每一集静态代码块中的代码,都会被 Java 编译器置于同一方法中,命名为 。

类的初始化,就是为标记常量的字段赋值,以及执行 方法的过程。Java 虚拟机会通过枷锁来确保类的 方法只被执行一次。

举例一下情况会触发类的初始化:
1:虚拟机启动时,初始化用户指定的主类。
2:遇到 new 指令时,初始化 new 指令的目标类。
3:当遇到调用静态方法的指令时,初始化该静态方法所在的类。
4:当遇到访问静态字段的指令时,初始化该静态方法所在的类。
5:子类的初始化会触发父类的初始化。
6:如果一个接口定义了 default 方法,那么实现该接口的类初始化时,会触发接口的初始化。
7:使用反射 API 对某个类进行反射调用时,初始化该类。

问答

Q:新建类,和新建类的数组,初始化过程

新建类的时候,需要加载,链接和初始化。新建类的数组的时候,由于并没有使用类,所以只需要加载该类。如果需要使用该类了,在执行类的链接和初始化。

Q:类的初始化和实例的初始化区别,初始化后的类存储在什么地方

类的初始化只有一次,通过类的加载链接生成对应的数据结构,存储在元空间。实例的初始化可以有多次。

Q:类中的静态字段,如果没有被 JVM 标记为常量,那么如何分配内存

加载类的过程,都会分配内存,只是初始化的时候不一样:一个是在 JVM 中直接复制,一个是在 clinit 方法中复制。

Q clinit 执行时的锁,是什么锁,跟 synchronized 一样吗

clinit 执行时的锁是虚拟机内部锁,和 synchronized 不一样。

总结

本文创作灵感来源于 极客时间 郑雨迪老师的《深入拆解 Java 虚拟机》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。

关注本人公众号,第一时间获取最新文章发布,每日更新一篇技术文章。

03 Java 虚拟机是如何加载 Java 类的的更多相关文章

  1. 《深入理解Java虚拟机》- Java虚拟机是如何加载Java类的?

    Java虚拟机是如何加载Java类的?  这个问题也就是面试常问到的Java类加载机制.在年初面试百战之后,菜鸟喜鹊也是能把这流程倒背如流啊!但是,也只是字面上的背诵,根本就是像上学时背书考试一样. ...

  2. JAVA之中出现无法加载主类的情况解决方法

    j今天打代码的时候出现了无法加载主类的情况,我就收集了一些,java无法加载主类的方法 ava无法加载主类解决办法 今天启动项目,又遇到找不到或无法加载主类的情况,清除项目后无法编译,class文件下 ...

  3. Java安全之动态加载字节码

    Java字节码 简单说,Java字节码就是.class后缀的文件,里面存放Java虚拟机执行的指令. 由于Java是一门跨平台的编译型语言,所以可以适用于不同平台,不同CPU的计算机,开发者只需要将自 ...

  4. JVM如何加载一个类的过程,双亲委派模型中有哪些方法

    1.类加载过程:加载.验证.准备.解析.初始化   加载   在加载阶段,虚拟机主要完成三件事: 1.通过一个类的全限定名来获取定义此类的二进制字节流. 2.将这个字节流所代表的静态存储结构转化为方法 ...

  5. Java虚拟机(三):Java 类的加载机制

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

  6. 《深入理解java虚拟机》笔记(8)类的加载机制

    一.类加载机制 类加载器将类的.class文件中的二进制数据读入到内存中,将其放在方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位 ...

  7. Java提高篇——JVM加载class文件的原理机制

    在面试java工程师的时候,这道题经常被问到,故需特别注意. 1.JVM 简介 JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从“Hello World ”开始的,然后 ...

  8. Java --ClassLoader创建、加载class、卸载class

    一.java提供了三种ClassLoader对Class进行加载: 1.BootStrap ClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库 ...

  9. 使用javassist运行时动态重新加载java类及其他替换选择

    在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...

随机推荐

  1. 46 Simple Python Exercises-Very simple exercises

    46 Simple Python Exercises-Very simple exercises 4.Write a function that takes a character (i.e. a s ...

  2. 在eclipse上搭建springBoot

    1,具体步骤网上有,需要注意的是,如果是maven项目,需要先下载maven,配置环境变量,再在eclipse-windows -- preference -- maven,选择usersetting ...

  3. netcat 详解

    简介 netcat 是一款调试 TCP/UDP 网络连接的利器,常被称作网络调试的瑞士军刀,可见其功能强大. netcat 在 Linux, Windows 等各大操作系统上都有对应等发行版,以下以 ...

  4. [转载]AngularJS快速开始

    AngularJS快速开始 Hello World! 开始学习AngularJS的一个好方法是创建经典应用程序“Hello World!”: 使用您喜爱的文本编辑器,创建一个HTML文件,例如:hel ...

  5. 如何解决EXCEL中的科学计数法

    EXCEL虽然能够有效的处理数据,尤其是数字的计算.但是,在单元格中输入数字的时候,很多时候都会受到科学计算法的困扰. 当单元格中输入的数字,超过11位时,就会自动变成科学计数法.无论您怎么调整列的宽 ...

  6. 3219: 求最高同学位置—C语言版

    3219: 求最高同学位置—C语言版 时间限制: 1 Sec  内存限制: 128 MB提交: 207  解决: 115[提交][状态][讨论版][命题人:smallgyy] 题目描述 设一维数组存放 ...

  7. Debug与Release版本的区别详解

    原文链接 Debug 和 Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动.如果我们愿意,我们完全可以把Debug和Release的行为完全颠 ...

  8. vue-awesome-swiper实现轮播图

    1.首先通过npm安装vue-awesome-swiper,我在项目中用的是2.6.7版本 npm install vue-awesome-swiper@2.6.7 –save 2. 在main.js ...

  9. 51nod——2478 小b接水(预处理 思维)

    我本来想把每个谷都处理了,想了下觉得不好办.后来看其他人写的是处理每个位置,把每个位置可以接的水累加起来.整挺好. #include <bits/stdc++.h> using names ...

  10. 【思维题 经典模型】cf632F. Magic Matrix

    非常妙的经典模型转化啊…… You're given a matrix A of size n × n. Let's call the matrix with nonnegative elements ...