Java-虚拟机-类加载机制/类加载器

三个大阶段
一:装载(三个小阶段)

1.装载:就是读取class文件的字节流,放到jvm中
2.验证:校验字节的正确性
3.准备:给静态变量分配内存并且根据相应类型赋默认值(注意此处是默认值)

二:链接(也叫解析阶段,分静态链接和动态链接)
把符号引用替换为指针引用,就是将方法名和类名替换成内存地址,可以认为是汇编里的call指令
三:初始化:对静态变量赋指定值,同时执行静态代码块

下面将用代码阐述上述逐个过程

public class MyClass {
    
    

	public static final int a = 1;
	public int b = 2;

	public void m1() {
    
    
		m2();
	}

	public void m2() {
    
    

	}
}

一.1:将MyClass.class文件通过字节数组读到jvm中
一.2:校验这些字节是不是和jvm定义的一样,假设int在jvm中的机器码是8B,那么此时要校验int a是不是8B a
一.3:使int a=0;
二:在jvm中m1方法肯定不能直接调用m2方法,因为jvm不知道m2是个什么东西,m1调用的应该是m2方法开始的内存地址
三:使int a=1;

关于双亲委派模型
双亲委派存在的意义

1.java的沙箱安全机制,我们自己不能创建java.lang开头的java类
2.避免重复加载类

什么时候需要打破双亲委派?

当需要同一个类,并且不同版本的时候
典型的例子就是tomcat的各种类加载器,tomcat实现了许多类加载器,主要目的就是为了实现使用相同名称但是版本又不相同的类

如何自定义类加载器

1.通常实现findclass,本质该方法也会调用loadClass
2.但是如果想打破双亲模型,则覆盖loadClass方法

日记:

下面这行代码会打印出null

System.out.println(String.class.getClassLoader());

因为String属于rt包下,由启动类加载器加载(bootstrap classloader),而启动类加载器由c++实现,所以这行代码打印null,因为java中没有启动类加载器

猜你喜欢

转载自blog.csdn.net/u011624903/article/details/113706544