分析类加载全过程

本文深入探讨Java虚拟机(JVM)中类加载的过程,包括链接、验证、准备、解析和初始化等关键步骤,并通过实例代码展示类的主动引用与被动引用的区别。

链接 将Java类的二进制代码合并到JVM的运行状态之中的过程 •
•验证:
– 确保加载的类信息符合JVM规范,没有安全方面的问题。
• 准备:
– 正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
• 解析
– 虚拟机常量池内的符号引用替换为直接引用的过程
初始化 •
• 初始化阶段是执行类构造器()方法的过程。类构造器()方法是由编译器自动收集 类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。
• 当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先出发其父类的初始化
• 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步。

package com.lzy.JVM;

public class Demo01 {
public static void main(String[] args) {
	A a=new A();
	System.out.println(A.width);
	A a2=new A();//类加载和初始化只有一次
}
}
class A extends A_Father{
	public static int width=100;
	static {
		System.out.println("静态初始化类A");
		width=300;
	}
	public A() {
		System.out.println("创建A类的对象");
	}
}
class A_Father{
	
	static {
		System.out.println("静态初始化A_Father");
	}
}

运行结果
静态初始化A_Father
静态初始化类A
创建A类的对象
300

分析:

创建A类的对象
运行以下代码时

    A a=new A();
	System.out.println(A.width);

运行结果:
静态初始化A_Father
静态初始化类A
创建A类的对象
300

说明,虽然创建A类对象,但它会先初始化父类。然后初始化自己,最后才打印结果

运行以下代码时:

    A a2=new A();

运行结果:
创建A类的对象
不在初始化父类和自己,说明类的加载和初始化只有那么一次

什么时候会发生类的初始化?甚么时候不会发生类的初始化?

• 类的主动引用(一定会发生类的初始化)

– new一个类的对象
– 调用类的静态成员(除了final常量)和静态方法
– 使用java.lang.reflect包的方法对类进行反射调用
– 当虚拟机启动,java Hello,则一定会初始化Hello类。说白了就是先启动main方法所在的类
– 当初始化一个类,如果其父类没有被初始化,则先会初始化他的父类

• 类的被动引用(不会发生类的初始化)

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

例:

package com.lzy.JVM;

public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
	//主动引用
	//new A();//new一个类的对象,会初始化
	//System.out.println(A.width);//调用类的静态成员,会初始化
	//Class.forName("com.lzy.JVM.A");// 使用java.lang.reflect包的方法对类进行反射调用 ,会初始化
	
	//被动引用
	//System.out.println(A.SMALL);//调用final常量,不会初始化,(用final修饰的为常量,对应类的被动引用第三条:引用常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中了))
	//A[]as=new A[10];
	System.out.println(B.width);//当访问一个静态域时,只有真正声明这个域的类才会被初始化
	                            //通过子类访问父类静态域时,子类并不会被初始化,但父类会初始化
}
}
class B extends A{
	static {
		System.out.println("静态初始化B");
	}
}
class A extends A_Father{
	public static int width=100;
	public static final int SMALL=0;
	static {
		System.out.println("静态初始化类A");
		width=300;
	}
	public A() {
		System.out.println("创建A类的对象");
	}
}
class A_Father{
	
	static {
		System.out.println("静态初始化A_Father");
	}
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值