JVM中java类的载入时机
Java虚拟机把描写叙述类的数据从Class文件载入到内存。并对数据进行校验、转换解析和初始化。终于形成能够被虚拟机直接使用的Java类型。这就是虚拟机的载入机制。
类从被载入到虚拟机内存中開始,到卸载出内存为止。它的整个生命周期包含了:载入(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(using)、和卸载(Unloading)七个阶段。
当中验证、准备和解析三个部分统称为连接(Linking),例如以下如所看到的。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center">
这七个阶段,载入、验证、准备、初始化和卸载这五个阶段的顺序是确定的。类的载入过程必须依照这个顺序来按部就班地開始,而解析阶段则不一定,它在某些情况下能够在初始化阶段后再開始。
类的生命周期的每个阶段通常都是互相交叉混合式进行的。一般会在一个阶段运行的过程中调用或激活另外一个阶段。
Java虚拟机规范没有强制性约束在什么时候開始类载入过程。可是对于初始化阶段,虚拟机规范则严格规定了有且仅仅有四种情况必需马上对类进行“初始化”(而载入、验证、准备阶段则必需在此之前開始)。这四种情况归类例如以下:
1.遇到new、getstatic、putstatic或invokestatic这4条字节码指令时。假设类没有进行过初始化,则须要先触发其初始化。生成这4条指令最常见的Java代码场景是:使用newkeyword实例化对象时、读取或者设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)时、以及调用一个类的静态方法的时候。
2.使用java.lang.reflect包的方法对类进行反射调用的时候。假设类没有进行过初始化,则须要先触发其初始化。
3.当初始化一个类的时候,假设发现其父类还没有进行过初始化,则须要触发父类的初始化。
4.当虚拟机启动时,用户须要指定一个运行的主类(包括main()方法的类),虚拟机会先初始化这个类。
对于这四种触发类进行初始化的场景,在java虚拟机规范中限定了“有且仅仅有”这四种场景会触发。这四种场景的行为称为对类的主动引用,除此以外的全部引用类的方式都不会触发类的初始化,称为被动引用。
以下通过三个实例来说明被动引用:
演示样例1:
父类SuperClass.java
public class SuperClass {
static{
System.out.println("SuperClass init!");
}
public static int value = 123;
}
子类SubClass.java
public class SubClass extends SuperClass {
static{
System.out.println("SubClass init!");
}
} 主类NotInitialization.java
public class NotInitialization {
public static void main(String[] args) {
System.out.println(SubClass.value);
}
}
输出结果: SuperClass init! 123
由结果能够看出仅仅输出了“SuperClass init!
”,没有输出“SubClass init。”。这是由于对于静态字段,仅仅有直接定义该字段的类才会被初始化。因此当我们通过子类来引用父类中定义的静态字段时,仅仅会触发父类的初始化,而不会触发子类的初始化。
演示样例2:
SuperClass[ ] scs=new SuperClass[11];
如上。当初始化一个对象数组的时候。也不会触发类的初始化。
演示样例3:
public class ConstClass {
static {
system.out.printl("const");
}
public static final int age =123;
}
public class NotInitialization{
public static void main(String[ ] args){
system.out.println(ConstClass.age);
}
此时并不会出现 “const”,由于在NotInitialization类在编译的时候已经把ConstClass中的变量age放在常量池中了,訪问时直接取出age就可以。不会引发ConstClass的初始化。
JVM中java类的载入时机的更多相关文章
- JVM中java类的加载时机(转载:http://blog.csdn.net/chenleixing/article/details/47099725)
Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的加载机制.类从被加载到虚拟机内存中开始,到卸载出内 ...
- JVM:Java 类的加载机制
虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制. 类的生命周期 类从被加载到虚拟机内 ...
- hibernate中java类的成员变量类型如何映射到SQL中的数据类型变化
hibernate映射文件??.hbm.xml配置映射元素详解--Hibernate映射类型 在从Hibernate的java的成员类型映射到SQL中的数据类型,其内映射方式它满足,SQL可以自己调制 ...
- MyEclipse2014中Java类右键Run as没有JUnit Test
Java初学,想试试连接本地数据库,按照百度经验中的方法,在最后执行测试的卡住了,为啥?因为MyEclipse中右键Run as没有JUnit Test选项! 6.1.测试数据库mysql是在项目中连 ...
- Maven项目中java类报错-Cannot resolve symbol
电脑蓝屏了,强制重启之后再打开IDEA里面的项目,所有Java类文件都在报Cannot resolve symbo错误,可以确定所有依赖的包都有引用且jar包没有冲突. 经查询找到这个解决方法: 在I ...
- JVM中java实例对象在内存中的布局
普通的Java对象实例 和 Java数组实例.Java数组实例的对象头多了一个数组的长度.Java虚拟机可以通过普通java对象的元数据来确定java对象的大小,但是从数组的元数据中却无法确定数组的 ...
- JVM中存储类信息的三个表格
摘自:<Java Performance>第三章 Internal Class Loading Data The HotSpot VM maintains three hash table ...
- IntelliJ IDEA中Java类注释
打开Idea,依次选择File-->Settings-->Editor-->File and CodeTemplates ,右侧tab选项卡点击Includes,选择File Hea ...
- Android Studio使用过程中Java类突然报红,但项目可运行解决方案
1.点击File->Invalidate Caches / Restart... 2.重启Gradle,清除缓存 3.Clean Project
随机推荐
- day-05 python函数
# #-*- coding:utf-8 -*-# 1:编写一个名为 make_shirt()的函数,它接受一个尺码以及要印到 T 恤上的字样.这个函数应打印一个句子,概要地说明 T 恤的尺码和字样.d ...
- K8S-删除Terminating状态的namespace
kubernetes 删除Terminating状态的命名空间 1.检查该namespace下是否还有资源: kubectl get all --namespace=cattle-system 2.删 ...
- 脑洞大开加偏执人格——可持久化treap版的Link Cut Tree
一直没有点动态树这个科技树,因为听说只能用Splay,用Treap的话多一个log.有一天脑洞大开,想到也许Treap也能从底向上Split.仔细思考了一下,发现翻转标记不好写,再仔细思考了一下,发现 ...
- MessageDigest 加密和解密2
package com.drawthink.platform.util; import java.security.MessageDigest; import java.security.NoSuch ...
- python--5、模块
模块 程序的代码根据作用分散写入多个文件,这些文件相互引用,以实现程序的功能,这些文件即称之为”模块“.自己定义的函数或者变量为了防止在解释器中执行完退出后丢失,需要把代码写到文件中,再直接执行,称为 ...
- Higher-Order Functions and Lambdas
https://kotlinlang.org/docs/reference/lambdas.html
- Python中join函数和os.path.join用法
Python中有join和os.path.join()两个函数,具体作用如下: join:连接字符串数组.将字符串.元组.列表中的元素以指定的字符(分隔符)连接生成一个新的字符串 os.path.jo ...
- Js 字符串中提取数字
一 parseInt()方法: 首先想到的是js提供的parseInt方法,例子: var str ="4500元"; var num = parseInt(str); alert ...
- python tips:作用域与名字空间
Python具有静态作用域,变量的作用域由它定义的位置决定,而与调用的位置无关. a = 2 def f(): a = 2 第一行的a的作用域是全局作用域,作用于定义位置后面的所有位置. 第四行的a的 ...
- scrapy-redis使redis不止保存url
先看scrapy-redis源码 class RedisMixin(object): """Mixin class to implement reading urls f ...