Java 虚拟机的类加载机制

关于类加载机制:

​ 虚拟机把描述类的数据从Class 文件加载到内存,并对数据进行效验、转换解析和初始化,最终 形成可以被虚拟机直接使用的Java 类型,就是虚拟机的类加载机制。

1、初始化 时机

1、遇到 new 、getstatic 、putstatic 、invokestatic 这四个字节码指令时。触发这四条指令的场景:

  • 使用new 实例化对象时
  • 读取或设置一个类的静态字段(被final修饰,已在编译期把结果放入常量池的不算(即 常量不算,static final 修饰))
  • 调用一个类的静态方法

2、使用反射调用时,先进行初始化

3、初始化一个类时,若其父类未被初始化,则先初始化其父类。

4、当虚拟机启动时,用户需要指定一个要执行的主类(main() 函数所在的类),虚拟机会先初始化它。

5、jdk 7.0 中,动态语言的支持

以上称为主动引用,被动引用不会引起初始化:

现有如下两个类:

class SuperClass{
static {
System.out.println("SuperClass init !!!");
}
public static int value = 123;
} class SubClass extends SuperClass{
static {
System.out.println("SubClass init !!!");
} public static final String HELLO_WORLG = "hello world !";
}
  • 测试一:
  public static void main(String[] args) {
System.out.println(SubClass.value);
}

运行结果

  SuperClass init !!!
123
  • 对于静态变量,只有直接定义这个变量的类才会进行初始化,如子类调用父类的静态变量,只有父类会进行初始化,子类不会自动进行初始化。

  • 测试二:

  public static void main(String[] args) {
System.out.println(SubClass.HELLO_WORLG);
}

运行结果:

  hello world !
  • 常量在在编译期通过常量传播优化,将“hello world !“存储到了常量池中,也就是说,”SubClass.HELLO_WORLG“并没有通过SubClass类符号进行引用,二者并没有任何联系。所以不会导致该类初始化。

2、加载

  • 通过类的权限定名来获取此类的二进制字节流
  • 把字节流代表的静态数据结构转化为方法区的运行时数据结构
  • 在方法区中生成一个代表这个类的Class 对象

3、验证

​ 确保class文件的字节流中的信息是安全的,至少不会危害虚拟机自身的安全。只有通过了这阶段的验证,字节流才会进入内存的方法区进行存储。

4、准备

  • 类变量分配内存并设置初始零值,这些变量的内存在方法区中进行分配。

  • 常量会设置最终值,如:

  public static int value = 123;
public static final int con = 234;

准备期过后,会把value置为0,con的值置为234。

5、解析

​ 将常量池中的符号引用替换为直接引用。这一阶段会根据需要发生在初始化之前或之后,包含类或接口解析、字段解析、方法解析。

符号引用是无关虚拟机实现的内存布局。直接引用是和虚拟机实现内存布局相关的,符号引用必须在运行期转换获得真正的内存入口地址。

6、初始化

​ 开始真正执行类中定义的 Java 代码,初始化阶段是执行类构造器() 方法的过程

  • () 是编译期收集类中所有的类变量的赋值动作静态语句块中(static{})的语句结合而成的。静态语句块只能访问惊天语句块之前的变量,定义在其之后的变量,只能赋值,不能访问
  static {
i = 0; //可以给变量赋值编译通过
System.out.println(i); //使用变量编译不通过
} static int i;
  • () 方法和构造函数不同。子类不会显示的调用父类的init() 方法,但是虚拟机会保证子类init() 方法被调用之前,父类的init() 会被先调用。
  public class InitDemo_2 {
public static void main(String[] args) {
System.out.println(SubClass1.B);
}
} class SuperClass1{
public static int A = 1;
static {
A = 2;
}
}
class SubClass1 extends SuperClass1{
public static int B = A;
}

运行结果:

  2
  • 接口中不会有静态语句块,但是接口中可以有赋值语句,因此接口也会生成() ,但是,执行接口的() 不需要先执行父类的() ,除非父类的变量被执行,才会调用父类的() 。
  • () 方法只会被执行一次

7、类加载机制

三种类加载器

  • 启动类加载器(Bootstrap ClassLoader)
​	负责加载 JAVA_HOME/lib 目录下,或被-XbootclassPath 参数指定的路径下的类库。
  • 拓展类加载器(Extension ClassLoader)

    ​ 负责加载 JAVA_HOME/lib/ext 目录下或者被 java.ext.dirs 系统变量所指定的路径中的所有类库。

  • 应用程序类加载器(Application ClassLoader)

    ​ 是ClassLoader.getSystemClassLoasder() 方法的返回值,负责加载用户类路径上所指定的类库。

双亲委派模型

  • 类加载器通过组合的方式建立的父子关系,称为双亲委派模型。

  • 类需要有加载他的类加载器和类本身一起确定其在虚拟机中的唯一性。

  • 工作流程

    ​ 一个类加载器收到了类加载加载的请求,他首先不会尝试自己加载这个类而是把这个请求委派给父类加载器来完成。只有父类无法完成这个请求时,子加载器才会尝试自己去加载。

  • 作用

    ​ Java 类随着他的类加载器一起具备了一种带优越级的层级关系,所有的加载请求都会传送到顶层的启动类加载器中,保证了Java 的稳定运行。

java 虚拟机的类加载机制的更多相关文章

  1. 深入理解java虚拟机【类加载机制】

    Java虚拟机类加载过程是把Class类文件加载到内存,并对Class文件中的数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型的过程. 在加载阶段,java虚拟机需要完成以下 ...

  2. Java虚拟机:类加载机制详解

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 大家知道,我们的Java程序被编译器编译成class文件,在class文件中描述的各种信息,最终都需要加载到虚拟机内存才能运行和使用,那么 ...

  3. java虚拟机的类加载机制

    引言 我们写的代码是放在.java文件中,经过编译器编译后,转成.class文件.Class文件是一串二进制流,它可以被各平台的虚拟机所接受,实现跨平台.      虚拟机将描述类的数据从class文 ...

  4. 深入理解Java虚拟机(类加载机制)

    文章首发于微信公众号:BaronTalk 上一篇文章我们介绍了「类文件结构」,这一篇我们来看看虚拟机是如何加载类的. 我们的源代码经过编译器编译成字节码之后,最终都需要加载到虚拟机之后才能运行.虚拟机 ...

  5. 【进阶之路】深入理解Java虚拟机的类加载机制(长文)

    我们在参加面试的时候,经常被问到一些关于类加载机制的问题,也都会在面试之前准备的时候背好答案,但是我们是否有去深入了解什么是类加载机制呢?这段时间因为一些事情在家看了些书,这次就和大家分享一些关于Ja ...

  6. 深入理解Java虚拟机之类加载机制篇

    概述 ​ 虚拟机把描述类的数据从 Class 文件加载到内存中,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,就是虚拟机的类加载机制. ​ 在Java语言里面,类型的 ...

  7. Java虚拟机之类加载机制

    ⑴背景   Java虚拟机把Class文件加载到内存中,并对数据进行校验,转换解析,和初始化,最终形成被虚拟机直接使用的Java类型,这就是类加载机制. ⑵Jvm加载Class文件机制原理 类的生命周 ...

  8. 深入理解java虚拟机(三)-----类加载机制

    类加载机制jvm把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被jvm直接使用的java类型.在java中,类型的加载.连接和初始化都是在程序运行期间完成的 ...

  9. 《java虚拟机》----类加载机制

    No1: 实现语言无关性的基础仍然是虚拟机和字节码存储格式,虚拟机只与Class文件这种特定的二进制文件格式所关联,并不关心Class的来源是何种语言. No2: Class文件是一组以8位字节为基础 ...

随机推荐

  1. 将JavaScript转化为C#

    因为一个需求,不得不将JavaScript转化为C#. 其实有强大的 Node.js. 说说代码, 其实可以使用dynamic 来实现.但是dynamic有很多问题. 直接上代码吧,不是很难,就是很啰 ...

  2. 学习flex布局(弹性布局)

    Flex是Flexible Box的缩写,意为弹性布局.是W3C早期提出的一个新的布局方案.可以便捷的实现页面布局,目前较高版本的主流浏览器都能兼容,兼容情况如下: Flex在移动端开发上已是主流,比 ...

  3. WPF 绑定密码

    我们发现我们无法绑定密码框的密码,PasswordBox 的 Password 不能绑定. 我们想做 MVVM ,我们需要绑定密码,不能使用前台 xaml.cs 监听 密码改变得到密码的值,传到 Vi ...

  4. 转:C++输入一行字符串的一点小结

    原文链接: http://www.wutianqi.com/?p=1181 大家在学习C++编程时,一般在输入方面都是使用的cin.而cin是使用空白(空格,制表符和换行符)来定字符串的界的.这就导致 ...

  5. mb_substr函数

    定义和用法 mb_substr() 截取字符串中指定长度字符 注:常用于中文截取,可以避免截取时候出现乱码,即截取半个字符的情况. 类似函数 substr(),iconv_substr() 语法 mb ...

  6. 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结

    前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...

  7. 在打开Dreamweaver软件情况下,vs2010 asp项目无法调试

    会出现以下情况,只要关闭Dreamweaver就可以正常调试vs2010 asp项目.

  8. 03Vue事件

    Vue提供了事件的绑定,方法写在methods对象中. 绑定dom中有两种方法: 方法一:v-on:click/dblclcick/mouseOver/mouseOut="方法名" ...

  9. Zookeeper 笔记-watch

    ZooKeeper对Watch提供了什么保障 对于watch,ZooKeeper提供了这些保障: Watch与其他事件.其他watch以及异步回复都是有序的. ZooKeeper客户端库保证所有事件都 ...

  10. yii2之数据验证

    一.场景 什么情况下需要使用场景呢?当一个模型需要在不同情境中使用时,若不同情境下需要的数据表字段和数据验证规则有所 不同,则需要定义多个场景来区分不同使用情境.例如,用户注册的时候需要填写email ...