了解类载入全过程,有助于了解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");
}
}

JVM类载入过程及主动引用与被动引用的更多相关文章

  1. jvm学习002 虚拟机类加载过程以及主动引用和被动引用

    虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 类从被加载到虚拟机内存中开始,到卸载出内存为 ...

  2. Java中对类的主动引用和被动引用

    1.遇到new,getstatic,putstatic,invokestatic这4条字节码指令时,类如果没初始化就会被初始化,创建对象,读取或设置静态字段,调用静态方法. 2.反射 3.子类初始化前 ...

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

    一. 类的生命周期 类从被载入到虚拟机内存中開始,到卸载出内存为止,有下面(如图)的生命周期: 以上"载入->验证->准备->解析->初始化"称为类的载入过 ...

  4. JVM 类加载过程、初始化、主动引用、被动引用、静态初始化块执行顺序

  5. finalkeyword对JVM类载入器的影响

    众所周知,当訪问一个类的变量或方法的时候.假设没有初始化该类.就会先去初始化一个类 可是,当这个类的变量为final的时候,就不一定了 请看以下的样例 package com.lala.shop; i ...

  6. JVM系列文章(四):类载入机制

    作为一个程序猿,只知道怎么用是远远不够的. 起码,你须要知道为什么能够这么用.即我们所谓底层的东西. 那究竟什么是底层呢?我认为这不能一概而论.以我如今的知识水平而言:对于Web开发人员,TCP/IP ...

  7. jvm载入过程

    类载入过程 类从被载入到虚拟机内存中開始,到卸载出内存为止,它的整个生命周期包含:载入.验证.准备.解析.初始化.使用和卸载七个阶段.它们開始的顺序例如以下图所看到的: 当中类载入的过程包含了载入.验 ...

  8. 深入研究Java类载入机制

    深入研究Java类载入机制   类载入是Java程序运行的第一步,研究类的载入有助于了解JVM运行过程,并指导开发人员採取更有效的措施配合程序运行. 研究类载入机制的第二个目的是让程序能动态的控制类载 ...

  9. java类载入器——ClassLoader

    Java的设计初衷是主要面向嵌入式领域,对于自己定义的一些类,考虑使用依需求载入原则.即在程序使用到时才载入类,节省内存消耗,这时就可以通过类载入器来动态载入. 假设你平时仅仅是做web开发,那应该非 ...

随机推荐

  1. 取值对比ture of false加引号与不加引号的问题-----Bug笔记-160219

    一.默认情况,当属性值为布尔值类型的时候对比判断不用加引号<input type="radio" name="city" value="BeiJ ...

  2. ip输入框键入.或者合法数字自动选择下一个输入框效果

    <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8& ...

  3. php脚本业务逻辑

    设置时区 设置执行不超时 设置根目录常量 引入配置文件(自定义/模板) 错误记录 定义业务类 执行业务类::run() 数据库单例初始化(连接) 日志单例初始化(引入日志类,配置日志路径,日志开关) ...

  4. IS about 64bit system

    This function supports the 64-bit parts of the registry by using the REGDB_OPTION_WOW64_64KEY option ...

  5. Android PackageManager packages.xml文件格式

    packages.xml文件存放在/data/system目录下    该文件记录了系统中所有应用程序的包管理相关信息    PmS根据该文件进行包管理的各种操作 标签名称 所包含的值举例 last- ...

  6. c++/MFC 封装好的文件内存映射类

    整理日: 2015年2月16日 首先介绍内存映射文件操作------函数的用法以及先后执行顺序 // 第一步:创建文件 HANDLE hFile = CreateFileForMapping(_T(& ...

  7. [转]DOS命令

    windows dos命令 - 知识天地 - 博客园http://www.cnblogs.com/mfryf/archive/2012/02/13/2348685.html

  8. Codeforces 731D Funny Game

    Description Once upon a time Petya and Gena gathered after another programming competition and decid ...

  9. Delphi 版本号(D1到XE6),发现一个delphi.wikia.com网站

    Borland Compiler Conditional Defines  Edit  Talk1 2,909PAGES ONTHIS WIKI   Product Name Version Cond ...

  10. C语言的static和extern关键字

    我的博客:www.while0.com 如果A.c要包含B.c里的一个变量或函数,则在A.c中要用extern关键字声明.注意: ①如果是包含的B.c里的函数,则在A.c里声明的时候可以不写exter ...