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. 详解m4文件

    最近在分析speex代码,发现编译过程中需要的一个speex.m4文件不知道是何方神圣,怀着对未知知识的渴望,跑到 某哥和某基问了一下,算是认识了,为了方便以后经常见面,这里就做个记录吧. M4实际上 ...

  2. Jquery实现数据双向绑定(赋值和取值),类似AngularJS

    <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

  3. SQL 2008 外网访问说明

    1.  安装SQL2008 . 安装SQL2008之前,必须预先安装.NET Framework 3.5,和Windows Installer 4.5 Redistributable. 可能产生错误: ...

  4. 深刻理解反射(Reflection)

    最近公司在搞自动化测试,由于版权问题,无法用 '录制脚本' 进行,也就没法用 VS 自带的 UITest 框架(蛋疼), 所以只能开源的 FlaUI 框架来搞了.其中不可避免的涉及到反射的应用,但自己 ...

  5. 使用邮件监控Mxnet训练

    1. 前言 受到小伙伴的启发,就自己动手写了一个使用邮件监控Mxnet训练的例子.整体不算复杂. 2. 打包训练代码 需要进行监控训练,所以需要将训练的代码打包进一个函数内,通过传参的方式进行训练.还 ...

  6. 从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD

    第1部分:http://www.cnblogs.com/cgzl/p/7637250.html 第2部分:http://www.cnblogs.com/cgzl/p/7640077.html 第3部分 ...

  7. python爬虫爬取代理IP

    # #author:wuhao # #--*------------*-- #-****#爬取代理IP并保存到Excel----#爬取当日的代理IP并保存到Excel,目标网站xicidaili.co ...

  8. SQL数据库的基础操作

    一,认识SQL数据库 美国Microsoft公司推出的一种关系型数据库系统.SQLServer是一个可扩展的.高性能的.为分布式客户机/服务器计算所设计的数据库管理系统,实现了与WindowsNT的有 ...

  9. Linux入门(4)——Ubuntu16.04安装MATLAB2016b

    通常有三个安装文件: Matlab 2016b Linux64 Crack.rar R2016b_glnxa64_dvd1.iso R2016b_glnxa64_dvd2.iso sudo apt i ...

  10. jQuery 常用操作(转)

    一.书写规则 支持链式操作: 在变量前加"$"符号(var $variable = jQuery 对象): 注:此规定并不是强制要求. 二.寻找元素 选择器 基本选择器 层级选择器 ...