Java学习笔记-虚拟机类加载机制

来源:互联网 发布:java修改文件权限 编辑:程序博客网 时间:2024/05/17 22:39

概述

我们都知道,java的世界里有一句名言“一次编写,到处运行”,这是怎么做到的呢?

这就涉及到了虚拟机的相关内容,简单的来说,虚拟机就像一个API接口,只要把符合虚拟机规范要求的东西给它,他就能正确运行。这里说到的“符合虚拟机规范的东西” 其实就是class文件—一种二进制字节流。
也就是说,不管最上层用什么语言编写的代码,只要能编译成符合虚拟机规范的字节流,就能被jvm运行,所以像Groovy等也能在jvm上运行。

那么,关于虚拟机类加载,我想从三方方面来说明:
1, 类加载的时机
2, 类加载的方式
3, 类加载的过程
4, 类加载到虚拟机内存后,class文件中数据的变化

一,类加载的时机

虚拟机规范规定了以下4中方式会触发类加载:
(1) 碰到new、putstatic、getstatic、invokestatic这四条字节码指令时,如果该类没有初始化,则触发类加载,也就是说我们通过new来实例化一个类的时候,会触发类加载
(2) 使用java.lang.reflect包的方法对类进行反射调用时触发类加载
(3) 当初始化一个类的时候,发现其父类没有初始化,则触发
(4) JVM启动时,程序指定一个执行的主类(包含Main方法的类),虚拟机会先初始化该类

二,类加载的方式

首先,提到一个概念,就是类加载器(classLoader),它用于实现类加载动作。没一个类加载器都有一个单独的类名称空间,对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立它在虚拟机中的唯一性,也就是说,对两个来源于同一个Class文件的类,如果由不同的两个类加载器进行加载,那么这两个类是不同的。

1, 虚拟机中类加载器类型
从java虚拟机角度来说,只存在两种类加载器,启动类加载器和其他类加载器。其中启动类加载是由C++实现,是虚拟机的一部分。而其他类加载器都是由java实现,独立于虚拟机外部并全部继承自java.lang.ClassLoader。
从java开发人员的角度来看,类加载器可以划分细一些,包括:
(1) 启动类加载器
(2) 扩展类加载
(3) 应用类加载
(4) 自定义类加载器

2, 双亲委派机制
如果一个类加载器收到类加载请求,它首先不会自己尝试进行类加载,而是将这个请求委派给父类进行处理,每层类加载器都是如此,直到请求到达顶层启动类加载器,只有父类自己无法完成类加载时,子类才尝试自己加载,这就是类加载的双亲委派机制。

三,类加载的过程

class从被加载到虚拟机内存中开始,到卸载出内存为止,需要进过如下的步骤:
这里写图片描述
其中,前4个阶段为类加载过程。
1, 加载loading
是指通过一个全限定名称获取一个二进制字节流(class文件),并将整个字节流所代表的静态存储结构转化为方法区的运行时数据,最后在内存中生成一个java.lang.Class对象,用来作为访问方法区中这个类各种数据的入口。
2, 验证
该阶段主要是对loading到内存中的class文件的合法性进行验证,主要是为了保证class文件中的信息符合当前虚拟机要求,主要包括了如下几个方面:
(1) 文件格式验证
主要验证class字节流是否符合Class文件格式要求,并且能被当前虚拟机处理。比如魔数验证、主次版本号等
(2) 元数据验证
主要是对字节码描述的信息进行语义分析,以保证其描述符合java规范要求
(3) 字节码验证
(4) 符号引用验证
3, 准备
该阶段主要是对类变量进行内存空间分配,并赋予初始值,这些变量使用的内存都在方法区中。
存在两种情况:
(1)public static int value = 12;
这种情况下,value在准备阶段赋值为0,而不是12,只有在真正执行java代码时才会赋值12.
(2)public static final int value = 123;
这种情况下,value在准备阶段赋值为123,因为它定义为常量。
4, 解析
该阶段主要是虚拟机将常量池中的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄、调用点限定符这7种符号引用。

欢迎指正拍砖~~~~

1 0
原创粉丝点击