JVM类载入过程及主动引用与被动引用

简介:

了解类载入全过程,有助于了解JVM执行过程,以及更深入了解java动态性(解热部署,动态载入),提高程序灵活性。

类载入全过程:

JVM将class文件字节码文件载入到内存中。并对数据进行校验解析和初始化,终于形成能够直接使用的java类型的过程。


载入

将class文件字节码内容载入到内存中,并将这些静态数据转换成方法区中的执行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的訪问入口。

链接

将Java类的二进制代码合并到JVM的执行状态之中的过程。

验证

确保载入的类信息符合JVM规范,没有安全方面的问题。

准备

正式为类变量(static变量)分配内存。并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。

解析

虚拟机常量池内的符号引用替换为直接引用的过程。

初始化

初始化阶段是执行类构造器<clinit>()方法的过程。


类构造器<clinit>()方法是由编译器自己主动收集类中的全部类变量的赋值动作和静态语句块(static块)中的语句合并产生的。

当初始化一个类的时候,假设发现其父类还没有进行过初始化、则须要先触发其父类的初始化。

虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。


当訪问一个java类的静态域时。仅仅有真正声明这个域的类才会被初始化。

使用

卸载

类载入Demo:

package JVMProcess;
public class Demo {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.width);
    }
}

class A{
    public static int width = 100;

    static{
        System.out.println("静态初始化类A");
        width = 30; 
    }

    public A(){
        System.out.println("创建A类的对象");
    }
}

执行结果:

静态初始化类A
创建A类的对象
30

初始化过程Demo

package JVMProcess;

public class DemoInit {
    static
    {
        System.out.println("静态初始化DemoInit");
    }

    public static void main(String[] args) {
        System.out.println("DemoInit的main方法");
        AInit a = new AInit();
        System.out.println(AInit.width);
        AInit a2 = new AInit(); //类仅仅会载入和初始化一次,对象能够new多个。
    }
}

class AInit extends AInit_Father
{
    public static int width = 100;//静态变量,静态域 field
    static
    {
        System.out.println("静态初始化类AInit");
        width = 30;

    }
    public AInit()
    {
        System.out.println("创建AInit类的对象");
    }
}

class AInit_Father{
    static{
        System.out.println("静态初始化AInit_Father");
    }
}

被动引用和主动引用

类的主动引用(一定会发生类的初始化) 
new一个类的对象。


调用类的静态成员(除了final常最)和静态方法。 
使用java.lang.reflect包的方法对类进行反射调用。 
当虚拟机启动,java Hello则一定会初始化Hello类。

说白了就是先启动main方法所在的类。


当初始化一个类,假设其父类没有被初始化,则先会初始化他的父类。

类的被动引用(不会发生类的初始化) 
当訪问一个静态域时。仅仅有真正声明这个域的类才会被初始化。 
通过子类引用父类的静态变量,不会导致子类初始化。 
通过数组定义类引用,用不会触发此类的初始化。 
引用常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中了)

被动引用和主动引用Demo

package JVMProcess;

public class MPRefDemo {

    public static void main(String[] args) throws ClassNotFoundException {
        //主动引用
        //new AInitRef();
        //System.out.println(AInitRef.width);会初始化AInitRef
        //反射调用也会初始化
        //Class.forName("JVMProcess.AInitRef");

        //被动引用
        //常量
        //System.out.println(AInitRef.MAX);//不会初始化AInitRef
        //数组定义类引用
        //AInitRef[] as = new AInitRef[10];
        //System.out.println(B.width);//B不会初始化,AInitRef会初始化
        System.out.println(B.MAX);//B和AInitRef都不会初始化
    }
}


class B extends AInitRef
{
    static
    {
        System.out.println("静态初始化类B");
    }
}

class AInitRef extends AInit_FatherRef
{
    public static int width = 100;//静态变量。静态域 field
    final static int MAX = 100;

    static
    {
        System.out.println("静态初始化类AInit");
        width = 30;

    }
    public AInitRef()
    {
        System.out.println("创建AInit类的对象");
    }
}

class AInit_FatherRef{
    static{
        System.out.println("静态初始化AInit_Father");
    }
}





本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5321894.html,如需转载请自行联系原作者
相关文章
|
4月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
411 55
|
2月前
|
存储 Java 编译器
深入理解Java虚拟机--类文件结构
本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
|
5月前
|
Arthas 监控 Java
Arthas sc(查看JVM已加载的类信息 )
Arthas sc(查看JVM已加载的类信息 )
190 9
|
7月前
|
存储 算法 Java
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
91 6
|
6月前
|
Java
jvm类常见加载顺序
jvm类常见加载顺序
|
12月前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
279 35
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
11月前
|
缓存 前端开发 Java
JVM知识体系学习二:ClassLoader 类加载器、类加载器层次、类过载过程之双亲委派机制、类加载范围、自定义类加载器、编译器、懒加载模式、打破双亲委派机制
这篇文章详细介绍了JVM中ClassLoader的工作原理,包括类加载器的层次结构、双亲委派机制、类加载过程、自定义类加载器的实现,以及如何打破双亲委派机制来实现热部署等功能。
503 3
|
11月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
209 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
监控 Java 测试技术
滚雪球学Java(45):探秘Java Runtime类:深入了解JVM运行时环境
【5月更文挑战第20天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
141 1
滚雪球学Java(45):探秘Java Runtime类:深入了解JVM运行时环境
|
Java Perl
JVM内存问题之如何统计在JVM的类加载中,每一个类的实例数量,并按照数量降序排列
JVM内存问题之如何统计在JVM的类加载中,每一个类的实例数量,并按照数量降序排列
196 0