03 Java 虚拟机是如何加载 Java 类的
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 类的的更多相关文章
- 《深入理解Java虚拟机》- Java虚拟机是如何加载Java类的?
Java虚拟机是如何加载Java类的? 这个问题也就是面试常问到的Java类加载机制.在年初面试百战之后,菜鸟喜鹊也是能把这流程倒背如流啊!但是,也只是字面上的背诵,根本就是像上学时背书考试一样. ...
- JAVA之中出现无法加载主类的情况解决方法
j今天打代码的时候出现了无法加载主类的情况,我就收集了一些,java无法加载主类的方法 ava无法加载主类解决办法 今天启动项目,又遇到找不到或无法加载主类的情况,清除项目后无法编译,class文件下 ...
- Java安全之动态加载字节码
Java字节码 简单说,Java字节码就是.class后缀的文件,里面存放Java虚拟机执行的指令. 由于Java是一门跨平台的编译型语言,所以可以适用于不同平台,不同CPU的计算机,开发者只需要将自 ...
- JVM如何加载一个类的过程,双亲委派模型中有哪些方法
1.类加载过程:加载.验证.准备.解析.初始化 加载 在加载阶段,虚拟机主要完成三件事: 1.通过一个类的全限定名来获取定义此类的二进制字节流. 2.将这个字节流所代表的静态存储结构转化为方法 ...
- Java虚拟机(三):Java 类的加载机制
1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 ...
- 《深入理解java虚拟机》笔记(8)类的加载机制
一.类加载机制 类加载器将类的.class文件中的二进制数据读入到内存中,将其放在方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位 ...
- Java提高篇——JVM加载class文件的原理机制
在面试java工程师的时候,这道题经常被问到,故需特别注意. 1.JVM 简介 JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从“Hello World ”开始的,然后 ...
- Java --ClassLoader创建、加载class、卸载class
一.java提供了三种ClassLoader对Class进行加载: 1.BootStrap ClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库 ...
- 使用javassist运行时动态重新加载java类及其他替换选择
在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...
随机推荐
- display:table的几个用法(元素平分宽度,垂直居中)
DIV+CSS的布局已经让表格布局几乎很少用到,除非表格语义性很强的情况. display:table解决了一部分需要使用表格特性但又不需要表格语义的情况, 尤其是DIV+CSS很不方便解决的问题,比 ...
- 为OSSIM添加 ossec的linux agent
1,安装环境 [root@node32 test]# yum groupinstall "Development Tools" -y Installed: byacc.x86_64 ...
- LeetCode Add Binary 两个二进制数相加
class Solution { public: string addBinary(string a, string b) { if(a==""&&b==" ...
- java之打印机服务通俗做法
javax.print包是API的主包,其中包含的类和接口能够让你:1)发现打印服务(Print Services)2)指定打印数据的格式 3)从一个打印服务创建打印工作(print jobs) 4) ...
- python_12_continue
for i in range(9): if i<3: print("loop",i) else: continue#跳出本次循环,继续到下一循环 print('hehe... ...
- Ribbon 负载均衡搭建
本机IP为 192.168.1.102 1. 新建Maven 项目 ribbon 2. pom.xml <project xmlns="http://maven.ap ...
- Javascript笔记部分
写入HTML输出 document.write(“<h1>”); 改变HTML内容 x = document.getElementById(“demo”) //查找元素 后面可以.valu ...
- swiper动画效果
参考swiper官方网站:http://www.swiper.com.cn/ Swiper常用于移动端网站的内容触摸滑动: 结构展示: 纯javascript打造的滑动特效插件,面向手机.平板电脑 ...
- 3170: [Tjoi2013]松鼠聚会
Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1804 Solved: 968[Submit][Status][Discuss] Descript ...
- mysql 索引的统计
查看一个库里面没有使用过的索引select object_type,object_schema,object_name,index_name,count_star,count_read,COUNT_F ...