[读书笔记]Java类载入过程

一. 类的生命周期

类从被载入到虚拟机内存中開始,到卸载出内存为止,有下面(如图)的生命周期:

以上“载入->验证->准备->解析->初始化”称为类的载入过程

Java虚拟机规范中没有对什么时候须要開始类载入的第一阶段进行强制约束,而是交给了虚拟机依据详细实现来自由把握。

可是对于初始化阶段,虚拟机有下面5种必须对类立即进行“初始化”的情况:

(1)遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,假设类还没初始化就须要立即触发其初始化。

常见场景:使用new实例化对象、读取或设置一个类的静态字段(除了编译器处理了的final字段)以及调用一个类的静态方法时。

(2)使用反射(java.lang.reflect包)对类进行调用时,也会触发类的初始化。

(3)当初始化一个类时,发现父类还未初始化时,要先触发父类的初始化。

(4)当虚拟机启动时,用户须要指定一个运行包括main方法的主类,虚拟机会初始化这个类。

(5)当使用JDK1.7的动态语言支持时,假设一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,触发相应的这个类的初始化。

以上5种场景的行为称为对一个类进行主动引用,除此之外的引用方式将不会触发类的初始化,称为被动引用。

下面是被动引用的一个列子:

class SuperClass
{
    static
    {
        System.out.println("SuperClass init!");
    }
    public static int value = 123;
}

class SubClass extends SuperClass
{
    static
    {
        System.out.println("SubClass init!");
    }
}

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

输出结果:

SuperClass init!

123

二.类的载入过程

1.载入

载入阶段进行过程:

(1)通过一个类的全限定名获取定义此类的二进制字节流;

(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;

(3)在内存中生成一个代表这个类的Java.lang.Class对象,作为方法区这个类的各种数据的訪问入口。

2.验证

验证是为了确保字节流包括信息符合当前虚拟机的要求,而且是安全的。

大概有四个验证阶段

(1)文件格式验证:验证字节流是否符合Class文件格式的规范。

(2)元数据验证:对字节码描写叙述的信息进行语义分析,目的是对类的元数据信息(数据类型)进行语义校验;

(3)字节码验证:对类方法体进行校验分析;

(4)符号引用验证:对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验。

这里能够做一个优化:由于验证阶段耗时还是挺大的,假如已被反复使用多次而且是验证过的代码就可以跳过这个步骤,加快类载入速度。

3.准备

正式为类变量(static)分配内存和设置类变量的初始值,这里的类变量除了被final修饰的。

4.解析

将符号引用替换成直接引用的过程。

5.初始化

运行类构造方法<clinit>()的过程。即static块语句的运行和变量的复制操作。

时间: 2024-11-10 00:12:08

[读书笔记]Java类载入过程的相关文章

[读书笔记] java类初始化

以下内容来自周志明的<深入理解java虚拟机>: 类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制. 到了初始化阶段,才真正开始执行类中定义的Java程序代码(或者说是字节码). 在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程.

读书笔记-----Java并发编程实战(一)线程安全性

线程安全类:在线程安全类中封装了必要的同步机制,客户端无须进一步采取同步措施 示例:一个无状态的Servlet 1 @ThreadSafe 2 public class StatelessFactorizer implements Servlet{ 3 public void service(ServletRequest req,ServletResponse resp){ 4 BigInteger i = extractFromRequest(req); 5 BigInteger[] fact

Java类载入器 ClassLoader的解析

//參考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类载入器基本概念 类载入器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之中的一个.它使得 Java 类能够被动态载入到 Java 虚拟机中并运行. 类载入器从 JDK 1.0 就出现了.最初是为了满足 Java Applet 的须要而开发出来的.Java Applet 须要从远程下载 Java 类文件到浏览器中并运行.如今类载入器在 Web 容

java类载入器——ClassLoader

Java的设计初衷是主要面向嵌入式领域,对于自己定义的一些类,考虑使用依需求载入原则.即在程序使用到时才载入类,节省内存消耗,这时就可以通过类载入器来动态载入. 假设你平时仅仅是做web开发,那应该非常少会跟类载入器打交道,但假设你想深入学习tomcatserver的架构,它是不可缺少的.所谓类载入器.就是用于载入Java类到Java虚拟机中,它负责读取Java字节码.并转换成java.lang.Class类的一个实例.使字节代码.class文件得以执行. 一般类载入器负责依据一个指定的类找到相

[读书笔记]Java类加载器

一.类与类加载器 类加载器除了在类加载阶段的作用外,还确定了对于一个类,都需要由加载它的类加载器和这个类本身一同确定其在Java虚拟机中的唯一性.通俗一点来讲,要判断两个类是否"相等",前提是这两个类必须被同一个类加载器加载,否则这个两个类不"相等". 这里指的"相等",包括类的Class对象的equals()方法.isAssignableFrom()方法.isInstance()方法.instanceof关键字等判断出来的结果. 示例:不同的类

Java类载入器(一)——类载入器层次与模型

类载入器 ??虚拟机设计团队把类载入阶段中的"通过一个类的全限定名来获取描写叙述此类的二进制字节流"这个动作放到Java虚拟机外部去实现.以便让应用程序自己决定怎样去获取所须要的类.实现这个动作的代码模块称为"类载入器". 类载入器层次(等级) ??从JVM的角度来讲,仅仅存在两种不同的类载入器. ??第一类是启动类载入器(Bootstrap ClassLoader):这个类载入器主要载入JVM自身工作须要的类.这个类载入器由C++语言实现(特指HotSpot).是

Java类装载过程

类装载过程由JVM类装载子系统负责,主要包括一下三个步骤: 1)装载:查找并装载类型的二进制数据到虚拟机中 1.通过某些途径,产生一个代表该类型的二进制数据流 2.解析二进制数据流为方法区的内部数据结构 3.在堆中创建一个表示该类型的Class实例(装载步骤的最终产品) 注意:Java虚拟机规范允许类装载器缓存Java类型的二进制表现形式,如果预装载出错,则要等待该类被主动使用时抛出LinkageError的子类的异常 2)连接: 1.验证 确保导入的类格式正确 检查final类不能有子类,fi

[读书笔记]Java类加载过程

一. 类的生命周期 类从被加载到虚拟机内存中开始,到卸载出内存为止,有以下(如图)的生命周期: 以上"加载->验证->准备->解析->初始化"称为类的加载过程. Java虚拟机规范中没有对什么时候需要开始类加载的第一阶段进行强制约束,而是交给了虚拟机根据具体实现来自由把握. 但是对于初始化阶段,虚拟机有以下5种必须对类立即进行"初始化"的情况: (1)遇到new.getstatic.putstatic或invokestatic这4条字节码指令

Effective Java 读书笔记之三 类和接口

一.使类和成员的可访问性最小化 1.尽可能地使每个类或者成员不被外界访问. 2.实例域决不能是共有的.包含公有可变域的类不是线程安全的. 3.除了公有静态final域的特殊情形之外,公有类都不应该包含公有域,并且确保公有静态final域所引用的对象不可变. 二.在公有类中使用访问方法而非公有域 1.如果类是包级私有的,或者是私有的嵌套类,直接暴露它的数据域并没有本质的错误. 2.公有类永远都不应该暴露可变的域. 三.使可变性最小化 不可变的类是指其实例不能被修改的类.为使类不可变,需要遵循以下五