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. 域名与IP地址的联系与区别

    我们也知道每一台机都有一个唯一ip地址, 特别难记,所以出现了今天的DNS(域名) 当我们的计算机想要和一个远程机器连接时,我们可以申请连接该机器ip地址下的DNS,例如:www.baidu.com. ...

  2. jquery datatable 获取当前分页的数据

    使用jquery datatable 遇到分页分别求和时,找了半天才找到获取当前分页数据的方法,以此总结 var table=$('#example').DataTable( { "pagi ...

  3. SAP成都研究院C4C光明左使:SAP Cloud for Customer 使用SAP UI5的独特之处

    大家好,今天的文章来自我的同事,Yang Joey. 2017年7月,SAP成都研究院C4C开发团队刚刚建立.某个周一早晨的Scrum meeting,新出现一位眉清目秀的小伙子,向大家自我介绍:&q ...

  4. Dynamic typing 动态类型

    https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Dyna ...

  5. vue安装环境

    vue安装环境 1. 安装node.js 先在电脑上安装node.js, https://nodejs.org/en/ 可以点击链接安装. 安装成功后,在命令板里检测是否安装成功, node -v 2 ...

  6. 2018.6.19 Java核心API与高级编程实践复习总结

    Java 核心编程API与高级编程实践 第一章 异常 1.1 异常概述 在程序运行中,经常会出现一些意外情况,这些意外会导致程序出错或者崩溃而影响程序的正常执行,在java语言中,将这些程序意外称为异 ...

  7. 跑rbgirshick的fast-rcnn代码

    需要安装Caffe.pycaffe cython.python-opencv.easydict matlab(主要用于对PASCALvoc数据集的评估) 为什么要bulid cython.caffe. ...

  8. python_73_pickle序列化(接72)

    # json(为字符串形式)用于不同语言之间的数据交互,只适用于简单的数据交互,字典之类可以,函数就不行了,如下例 ''' import json def say(name):print('Hi!', ...

  9. 对于无法激活的系统—使用rearm命令延长试用期

    1.首先安装后,有一个30天的使用期. 2.在30天试用期即将结束时,用rearm命令后重启电脑,剩余时间又回复到30天.微软官方文档中声明该命令只能重复使用3次,也说是说总共可以免费体验120天. ...

  10. 第十二篇、OC_仿淘宝商品详情页的翻页

    // // GFBProductViewController.m // elmsc // // Created by MAC on 2016/11/26. // Copyright © 2016年 G ...