深入理解Java虚拟机05--虚拟机类加载机制
一.前言
我们一定心里有个疑问,我们那个多态是怎么回事?我们指定的一个接口,却可以等到运行时可以对应于不同的实现类。这是因为,Java有个特性就是依赖运行期动态加载和动态连接,这样实现了Java可以动态进行扩展。我们甚至可以从网络或者其他的地方加载一个二进制流作为程序的一部分。所以,我们通过编译器将我们写的Java文件代码编译成Class文件,程序跑起来的时候通过加载器。
二.加载过程
1、 加载(loading)
三件大事
- 1、通过类的全限定名来定义这个类的二进制流
- 2、将字节流代表的静态存储结构变成方法区的运行时数据结构
- 3、在方法区生成一个java.lang.Class对象,作为方法区数据的访问入口
自定义类加载器:重写loadClass()方法
- 一个区别:数组类本身不通过类加载器创建,而是由虚拟机直接创建,但是数组的元素还是需要类加载器创建的;
2、 连接
(1)、 验证
- 确保Class文件的字节流中包含的信息符合当前虚拟机的要求,避免导致系统奔溃
- 验证类型
- 文件格式验证:保证输入的字节流能够正确的解析并存储于方法区之内,格式上符合Java类型信息;
- 元数据验证:对元数据信息进行语义上的校验
- 字节码验证:通过数据流和控制流分析,确定程序语义是合法的,保证方法运行时不会危害虚拟机;
- 符号引用验证:验证类是否找到到(NoSuchMothodError),访问性是否正常等等,保证解析动作能正常运行;
- 验证是重要但不是必须的,对于反复验证呢过的Class可以考虑使用-Xverify:none参数来关闭大部分的类验证措施;
(2)、准备:为类变量分配内存并设置初始值(如int为0)。
(3)、解析:
- 可以放在初始化之后进行,比如需要动态加载的情况下
- 将常量池中的符号引用替换为直接引用的过程
- 符合引用:一组符号来描述所引用目标,与虚拟机内存布局无关;
- 直接引用:直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。和内存布局有关,目标已经在内存中;
- invokedynamic:动态调用点限定符,程序实际运行到这条指令的时候,解析动作才能进行;
- 解析种类
- 类或接口的解析
- 字段解析
- 类方法解析
- 接口方法解析
3、初始化
- 必须要立即进行初始化的情况如下(主动引用:主动触发引用的类进行初始化):
- new(实例化对象)、getstatic、putstatic(读取或者设置静态字段)、invokestatic(调用类静态方法)这4个字节码指令
- java.lang.reflect包的方法反射调用,类若没有初始化必须先进行初始化
- 初始化一个类,父类没有初始化,必须先初始化父类(但是接口不用,只有用到父接口时,才会初始化)
- 虚拟机指定了main方法的类
- JDK1.7,java.lang.invoke.MethodHandle解析的句柄为REF_ getStatic、REF_ putStatic、REF_ invokeStatic,对应的类还没有被初始化
- 被动引用
- 子类引用父类的静态字段,只初始化父类,而不会触发初始化子类
- 通过数组定义来引用类,不会触发此类的初始化
- 常量在编译阶段会存入到调用类的常量池中,本质上没有直接应用调用到定义了常量的类,因此定义了常量的这个类不会触发初始化
- < cinit >()方法:编译器自动收集类中的类变量的赋值动作和static代码块中的程序语句,并且能自动触发父类的< cinit >()方法先进行初始化。遇到多线程并发的时候,会自动加锁,其他的线程会被阻塞。直到执行完毕。
4、 使用
5、 卸载
三.类加载器
1、唯一性
- 对于任何一个类,都需要和这个类的加载器与这个类共同确定在Java虚拟机中的唯一性,这里说的唯一性指的是“相等”,也就是我们平时说的Class对象的equals()、isAssiganableFrom()、isInstance()方法的返回结果;
2、双亲委派模型
- 特点:
当一个类的加载器收到了加载请求,不会自己先动手,而是委派给这个类的父类进行加载,如果找不到加载不了就反馈回来自己加载。这样的话,让Java的类一出生就有了很好的层次父子关系。当然也有一些手段去破坏这种关系而获得某种效果。
- 破坏:
双亲委派模型可以被破坏,推荐重写findClass()方法,而不是loadClass(),应用于热部署等技术;
四.小结
我们通过编译器先将我们写的.java代码编译为可执行的.class文件,那么如果我们需要真正的执行这个代码,还需要一个过程。这个时候加载器的角色就来了,加载器将首先要加载可执行文件,并变换数据结构。在初始化之前,我们还需要进行验证和准备。解析的过程可以在初始化之前,也可以在初始化之后(实现动态加载的时候—)。触发初始化的条件有几种,分为被动引用和主动引用两大类。我们可以理解为主动引用是我们主动的触发了本Class的初始化,比如New 这个对象的实例。 但是,也存在我们在本类中引用到了其他的类,比如说父类,其他类的常量。如果,我们的操作不是上述的主动引用,其结果是没有触发本Class的初始化,而是间接的触发了别的Class进行初始化工作。我们称这个为被动引用。对于任何一个类,我们通过类和这个类的加载器共同确定在JVM中的唯一性,为了保证父类和子类的层次关系。我们在有需求触发子类的初始化时,必须先完成父类的初始化工作,一直向上追溯,从上到下依次完成初始化。这就是所谓的双亲委派模型。双亲委派模型也是可以被破坏的,在热部署技术中有应用。
深入理解Java虚拟机05--虚拟机类加载机制的更多相关文章
- 《深入理解 Java 虚拟机》学习 -- 类加载机制
<深入理解 Java 虚拟机>学习 -- 类加载机制 1. 概述 虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的 J ...
- 深入理解java:1.1. 类加载器
从java的动态性到类加载机制 我们知道,Java是一种动态语言. 那么怎样理解这个“动态”呢? 或者说一门语言具备了什么特性,才能称之为动态语言呢? 对于java,我是这样理解的. 我们都知道J ...
- JVM虚拟机—JVM的类加载机制
1 什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 ...
- Java魔法堂:类加载机制入了个门
一.前言 当在CMD/SHELL中输入 $ java Main<CR><LF> 后,Main程序就开始运行了,但在运行之前总得先把Main.class及其所依赖的类加载到JVM ...
- Java基础篇(JVM)——类加载机制
这是Java基础篇(JVM)的第二篇文章,紧接着上一篇字节码详解,这篇我们来详解Java的类加载机制,也就是如何把字节码代表的类信息加载进入内存中. 我们知道,不管是根据类新建对象,还是直接使用类变量 ...
- 虚拟机系列 | JVM类加载机制
本文源码:GitHub·点这里 || GitEE·点这里 一.类加载简介 类的加载机制是指把编译后的.class类文件的二进制数据读取到内存中,并为之创建一个java.lang.Class对象,用来封 ...
- JVM虚拟机(一):类加载机制
类加载的时机 类加载的生命周期为: 加载.验证.准备.解析.初始化.使用.卸载七个阶段,其中验证.准备.解析三个阶段统称为连接.其中加载与连接时交叉执行的. 类必须初始化的六种情况 遇到new.g ...
- 深入理解Java中方法的参数传递机制
形参和实参 我们知道,在Java中定义方法时,是可以定义参数的,比如: public static void main(String[] args){ } 这里的args就是一个字符串数组类型的参数. ...
- 理解JAVA与C的运行机制
1.java的运行机制 java的编译过程,将java的源程序(扩展名为.java的文件),由java编译程序将java的字节码文件(.class文件)在jvm上运行,机器码有cpu运行, jvm编译 ...
- 深入理解Java自动装箱拆箱机制
1.自动装箱与拆箱的定义 装箱就是自动将基本数据类型转换为包装器类型(int-->Integer): 拆箱就是自动将包装器类型转换为基本数据类型(Integer-->int). Java中 ...
随机推荐
- [学习笔记]修改关键跳无效且关键CALL又不存在的情况
先用DI查下壳,VC++写的,无壳. 然后,打开软件看一下软件注册的情况 有弹窗,那载入OD看看能不能搜索到字符串 回到反汇编窗口,发现有两个JE都跳过了注册成功的代码 似乎很简单的样子,只要NOP掉 ...
- asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案
之前碰到asp.net core异步进行新增操作并且需要判断某些字段是否重复的问题,进行插入操作的话会导致数据库中插入重复的字段!下面把我的解决方法记录一下,如果对您有所帮助,欢迎拍砖! 场景:EFC ...
- Salesforce Sales Cloud 零基础学习(二) Account 和 Contact
上一篇我们讲了Sales Cloud 中关于一个公司的产品和定价手册的概念,产品需要卖给企业客户(包括渠道伙伴以及合作伙伴等等)或者是个人客户,那客户信息存在哪里?针对企业客户,通过谁去串联起和企业客 ...
- JwtBearer认证
ASP.NET Core 认证与授权[4]:JwtBearer认证 在现代Web应用程序中,通常会使用Web, WebApp, NativeApp等多种呈现方式,而后端也由以前的Razor渲染HT ...
- for循环输出漏斗的形状【java】
使用for循环语句输出以下“漏斗”效果: +------+ |\..../| | \../ | | \/ | | /\ | | /..\ | |/....\| +------+ 代码:(解决思路详见代 ...
- ES6躬行记(11)——对象
在第5篇中,讲解了多个对象字面量的改进,本节将重点介绍两个新增的静态方法,以及对象属性的重复处理和枚举顺序. 一.Object.is() 此方法用于判断两个值是否相同,内部实现了SameValue算法 ...
- 【Go】优雅的读取http请求或响应的数据-续
原文链接:https://blog.thinkeridea.com/201902/go/you_ya_de_du_qu_http_qing_qiu_huo_xiang_ying_de_shu_ju_2 ...
- 利用Python测量滴水湖的水面面积
美丽的滴水湖 美丽的滴水湖坐落在上海的东南角,濒临东海,风景秀丽,安静舒适,是旅游.恋爱的绝佳去处.笔者有幸去过一回,对那儿的风土人情留下了深刻的印象,如果有机会,笔者还会多去几次! 滴水湖是 ...
- RNN入门(二)识别验证码
介绍 作为RNN的第二个demo,笔者将会介绍RNN模型在识别验证码方面的应用. 我们的验证码及样本数据集来自于博客: CNN大战验证码,在这篇博客中,我们已经准备好了所需的样本数据集,不需要 ...
- .net里的ref、out、params参数。
1.ref參數 class Program { static void Main(string[] args) { int a = 10; ...