JVM 类型的生命周期学习
Java虚拟机通过装载、连接和初始化一个JAVA类型,使该类型可以被正在运行的JAVA程序所使用,其中,装载就是把二进制形式的JAVA类型读入JAVA虚拟机中;而连接就是把这种读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去。
连接阶段分为三个子步骤----验证、准备和解析。
"验证"步骤确保了JAVA类型数据格式正确并且适用于JAVA虚拟机使用。
"准备"步骤负责为该类型分配它所需的内存,比如为它的类变量分配内存。
"解析"步骤则负责把常量池中的符号引用转换为直接引用。
虚拟机的实现可以推迟解析这一步,它可以在当运行中的程序真正使用某个符号引用时再去解析它(把该符号引用转换为直接引用)。当验证、准备和(可选的)解析步骤都完成了时,该类型就已经为初始化做好了准备。在初始化期间都将给变量赋以适当的初始值。
所有的JAVA虚拟机实现必须在每个类或接口首次主动使用时初始化。下面这六种情况符合主动使用的要求。
(1)当创建某个类的新实例时(或通过在字节码中执行new指令;或者通过不明确的创建、反射、克隆或者反序列化)
(2)当调用某个类的静态方法时(即在字节码中执行invoke、static指令时)
(3)当使用某个类或接口的静态字段,或者对该字段赋值时,用final修饰的静态字段除外,它被初始化为一个编译时的常量表达式。
(4)当调用JAVA API中的某些反射方法时,比如类CLASS中的方法或者java.lang.reflect包中的类方法。
(5)当初始化某个类的子类时(某个类初始化时,要求它的超累已经被初始化了)
(6)当虚拟机启动时被表名为启动类的类(即含有main()方法的那个类)
装载
装载阶段由三个基本动作组成,要装载一个类型,JAVA虚拟机必须:
(1)通过该类型的完全限定名,产生一个代表该类型的二进制数据流。
(2)解析这个二进制数据流为方法去内的内部数据结构。
(3)创建一个表示该类型的java.lang.Class类的实例。
验证
当类型被装载后,就准备进行连接了。连接过程的第一步是验证---确认类型符合JAVA语言的语义,并且它不会危及虚拟机的完整性。检查被装载的类型是否有任何问题的整个过程都属于验证。
另一个很可能在装载时进行的检查是,确保除了Object之外的每一个类都有一个超类。在装载时检查的原因是当虚拟机装载一个类时,它必须确保该类的所有超类都已经被装载了。
在大部分虚拟机实现中,还有一种检查往往发生在正式的验证阶段之后,那就是符号引用的验证。在前面的章节中描述过,动态连接的过程包括通过保存在常量池中的符号引用查找被引用的类、接口、字段以及方法,把符号引用替换成直接引用。当虚拟机搜寻一个被符号引用的(类型、字段或方法)时,它必须首先确认该元素存在。
在正式的验证阶段需要完成的候选检查在下面列出:
(1)检查final的类不能拥有子类。
(2)检查final的方法不能被覆盖。
(3)确保在类型和超类型之间没有不兼容的方法声明(比如两个方法拥有相同的名字,参数再数量、顺序、类型上都相同,但是返回类型不同)这里超类需要在子类初始化前被初始化。
(4)检查所有的常量池入口相互之间一致。
(5)检查字节码的完整性。
(6)检查常量池中的所有的特殊字符串是否符合格式。
准备
在准备阶段,JAVA虚拟机为类变量分配内存,设置默认初始值。但在到达初始化阶段之前,类变量都没有被初始化为真正的初始值。JAVA虚拟机实现可能也为一些数据结构分配内存,目的是提高运行程序的性能。这种数据结构的雷子如方法表,它包含指向类中每一个方法(包括从超类继承的方法)的指针。
解析
类型经过了连接的前两个阶段---之后,它就可以进入解析阶段。解析过程是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用的过程。
初始化
一个类包含两个步骤:
1、如果累存在直接超类的话,且直接超类还没有被初始化,就先初始化直接超类。
2、如果累存在一个类初始化方法,就执行此方法。
当初始化一个类的直接超类的时候,也就是包含这两个步骤。因此,第一个初始化的类永远是Object,然后被主动使用的类的继承树上的所有类。超类总是在子类之前被初始化。
JAVA虚拟机必须确保初始化过程被正确的同步。如果多个线程需要初始化一个类,仅仅允许一个线程来执行初始化,其他的线程需要等待。当活动的线程完成了初始化过程之后,它必须通知其他的等待的线程。
卸载类型
虚拟机创建并初始化对象,使程序能使用对象,然后在对象变得不再被引用后可选地执行垃圾收集。同样,虚拟机装载、连接并初始化类,使程序能使用类,当程序不在引用它们的时候可选地卸载它们。

垃圾收集器必须从可触及的myThread类的对象,通过它在方法去中的类型数据找到可触及的CLASS实例。
从MyThread对象开始,垃圾收集器跟随一个指向MyThread的类型数据的指针,它找到了:
一个指向堆中的MyThread的Class实例的引用。
一个指向MyThread的直接超接口Cloneable的类型数据的指针。
一个指向MyThread的直接超类Thread的类型数据的指针。
从Cloneable的类型数据开始,垃圾收集器找到了:
一个指向堆中Cloneable的Class实例的引用
从Thread的类型数据开始,垃圾收集器找到了:
一个指向堆中Thread的Class实例的引用。
一个指向Thread的直接超接口Runnable的类型数据的指针。
一个指向Thread的直接超类Object的类型数据的指针。
从Runnable的类型数据开始,垃圾收集器找到了:
一个指向堆中Runnable的Class实例的引用。
从Object的类型数据开始,垃圾收集器找到了:
一个指向堆中Object的Class实例的引用。
仅仅一个可触及的MyThread的实例,垃圾收集器就可以触及MyThread和它所有超类型的Class实例。
参考:《深入java虚拟机》
JVM 类型的生命周期学习的更多相关文章
- JVM 类的生命周期、类加载器
类的加载.连接与初始化 • 1. 加载:查找并加载类的二进制数据 • 2. 连接 – 2.1 验证:确保被加载的类的正确性 ...
- Java对象在JVM中的生命周期
当你通过new语句创建一个java对象时,JVM就会为这个对象分配一块内存空间,只要这个对象被引用变量引用了,那么这个对象就会一直驻留在内存中,否则,它就会结束生命周期,JVM会在合适的时 ...
- C++异常之四 异常类型的生命周期
异常类型的生命周期 1. throw 基本类型: int.float.char 这三种类型的抛出和函数的返回传值类似,为参数拷贝的值传递. 1 int test_1(int num) throw (i ...
- 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期
一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...
- Java类型的生命周期
以上就是我今天没有总结学习类加载器时候对类加载器仅有的知识,虽然有个大概印象,但是还是有点模糊.今天一口气总结一下,参考文献我就不列举了.本文不生产知识,只是知识的搬运工. 静态.class文件到内存 ...
- Java - JVM - 类的生命周期
概述 简述 JVM 里 类的生命周期 上次写了 30%, 居然丢了 难受, 又要重新写 类的生命周期 加载 使用 卸载 1. 加载 概述 类型的加载 大体流程 装载 连接 验证 准备 解析(可选的) ...
- [Unity3D]脚本生命周期学习
脚本的生命周期 继承于MonoBehaviour的类对象无需手动实例化,由引擎来决定实例化的时机 Awake:每当脚本被加载的时候调用一次,就是说即使脚本没有被勾选,也会调用一次,主要用来做一些初始化 ...
- 测试Servlet生命周期学习笔记
测试环境:windows xp旗舰版 软件环境:myclipse8.5+tomcat7.0 ****************************************************** ...
- asp.net mvc生命周期学习
ASP.NET MVC是一个扩展性非常强的框架,探究其生命周期对用Mock框架来模拟某些东西,达到单元测试效果,和开发扩展我们的程序是很好的. 生命周期1:创建routetable.把URL映射到ha ...
随机推荐
- leetcode 105 Construct Binary Tree from Preorder and Inorder Traversal ----- java
Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...
- HDU 5234 Happy birthday --- 三维01背包
HDU 5234 题目大意:给定n,m,k,以及n*m(n行m列)个数,k为背包容量,从(1,1)开始只能往下走或往右走,求到达(m,n)时能获得的最大价值 解题思路:dp[i][j][k]表示在位置 ...
- linux下遍历目录(转-在于思考)
遍历目录的主要思想 由于目录就是一颗树,所以遍历目录就转换为遍历一棵树.谈到树的遍历就再熟悉不过了,有树的前序.层次和后序遍历,我使用的是前序遍历,后序遍历和前序遍历本质上一样,而层次遍历要比前两个麻 ...
- HDU 1507 Uncle Tom's Inherited Land*(二分图匹配)
Uncle Tom's Inherited Land* Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- 如何在远程计算机上运行PowerShell
问题: 不能在WORKGROUP里面的远程计算机里运行PowerShell指令,报错为用户名密码错 解决方法: 把两台机器上(远程计算机其和本机)都加入到trustedhosts 具体请参考 http ...
- Java——银行业务调度系统
需求: 模拟实现银行业务调度系统逻辑,具体需求如下: Ø 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口. Ø 有三种对应类型的客户:VIP客户,普通 ...
- CLR thread pool
Thread Pooling https://msdn.microsoft.com/en-us/library/windows/desktop/ms686756(v=vs.85).aspx Threa ...
- vim配置及插件安装管理(超级详细)[转]
1 写在前面 Linux下编程一直被诟病的一点是: 没有一个好用的IDE, 但是听说Linux牛人, 黑客之类的也都不用IDE. 但是对我等从Windows平台转移过来的Coder来说, 一个好用 ...
- Bitmap 之 getPixels() 的 stride
学习Graphics中遇到位图(Bitmap)中getPixels()方法,对该方法的用法大体理解,但对其中的stride参数却不明白具体的用法以及用意,现记述过程如下: getPixels()方法的 ...
- 使用Ef时,对一个或多个实体的验证失败。有关详细信息,请参见“EntityValidationErrors”属性。
EntityValidationErrors 关于如何查看 EntityValidationErrors 详细信息的解决方法 我们在 EF 的编程中,有时候会遇到这样一个错误: 但是,按照他的提示 ...