【JVM学习笔记】类的加载过程

一、类的生命周期概述

类的生命周期
类的生命周期

二、类的加载阶段 Loading

1 加载完成的操作

在这里插入图片描述

2 二进制流的获取

二进制流的获取方式

3 类模型与class实例的位置

类模型
实例的位置
说明
  反射的使用:

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test {

	public static void main(String[] args) {
		try {

			Class<?> cls = Class.forName("java.lang.String");
			Method[] ms = cls.getDeclaredMethods();

			for(Method m : ms) {

				String mod = Modifier.toString(m.getModifiers());
				System.out.print(mod + " ");

				String returnType = m.getReturnType().getSimpleName();
				System.out.print(returnType + " ");

				System.out.print(m.getName() + "(");
				Class<?>[] pt = m.getParameterTypes();
				if (pt.length == 0) System.out.print(')');

				for (int i = 0; i < pt.length; i++) {
					char end = (i == pt.length - 1) ? ')' : ',';
					System.out.print(pt[i].getSimpleName() + end);
				}

				System.out.println();

			}

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

}

3 数组类的加载

数组类

三、类的链接阶段 Linking

1 链接阶段的验证环节 Verification

验证环节
验证阶段
验证
验证

2 链接阶段的准备环节 Prepare

Prepare
注意事项

3 链接阶段的解析环节 Resolution

解析环节
println
解析环节
解析环节

四、类的初始化阶段 Initialization

1 类的初始化过程

类的初始化
类的初始化
  被static final修饰的引用变量是在初始化阶段进行赋值。但也有特例,例如static final修饰的String类型,如果是字面量方式进行赋值,那也是连接环节的准备阶段就进行赋值。或者像这样int a = new Random().nextInt();也是在初始化阶段赋值。

2 <clinit>()的线程安全性

clinit
clinit引起的死锁
  如下是通过<clinit>()实现的死锁:

package com.spd.jvm;

class A {

	static {

		try {
			Thread.sleep(1000);
			Class.forName("com.spd.jvm.B");
		} catch (InterruptedException | ClassNotFoundException e) {
			e.printStackTrace();
		}

		System.out.println("A finish init.");

	}

}

class B {

	static {

		try {
			Thread.sleep(1000);
			Class.forName("com.spd.jvm.A");
		} catch (InterruptedException | ClassNotFoundException e) {
			e.printStackTrace();
		}

		System.out.println("B finish init.");

	}

}

class DeadLockThread extends Thread {

	private final char flag;

	public DeadLockThread(char flag) {
		this.flag = flag;
		this.setName("Thread" + flag);
	}

	public void run() {
		try {
			Class.forName("com.spd.jvm." + flag);
		} catch(ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

}

public class Test {

	public static void main(String[] args) {

		DeadLockThread a = new DeadLockThread('A');
		DeadLockThread b = new DeadLockThread('B');

		a.start();
		b.start();

	}

}

3 类的主动使用和被动使用

主动使用
主动使用
被动使用
  主动使用中第八点和被动使用第四点了解一下就行,目前无需掌握。

五、类的卸载 Unloading

类的卸载
类的卸载
方法区的垃圾回收
类的卸载

六、类加载器的概述

1 概述

类加载器
类加载器

2 类加载器的分类

显示加载与隐式加载

package com.spd.jvm;

class User {

}

public class Test {

	public static void main(String[] args) {

		User user = new User(); // 隐式加载

		try {
			Class cls = Class.forName("com.spd.jvm.User"); // 显式加载
			ClassLoader.getSystemClassLoader().loadClass("com.spd.jvm.User"); // 显式加载
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

	}

}

3 类加载器的必要性

类加载器必要性

七、类加载器的命名空间与类加载器的分类

1 类加载器的命名空间

类的统一性
  同一个字节码文件被两个不同的类加载器加载,那就是两个类。

2 类加载器的分类

类加载器的分类
  上面这个图中,除了Bootstrap是用c/c++实现,其余都是用java实现的。
类加载器的分类
  (这个描述咋听起来像装饰模式)

八、关于不同类加载器的一些说明

1 启动类加载器

启动类加载器
  加入+TraceClassLoading这个参数,就能输出上面这种信息。

2 扩展类加载器

扩展类加载器

3 系统类加载器

系统类加载器

4 用户自定义类加载器

用户自定义类加载器
  数组对象的类加载器获取后打印出来是null,因为他不需要类加载器,自然也就没有。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九死九歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值