文章有点枯燥但是每个字都是我亲手码的因为这样我才能更好的掌握这些知识,所以耐心看吧,如果你想学习JVM,而不是当一个初级的搬运工或者CRUD工程师。
当我们使用java命令运行某个类的main函数时首先通过类加载器将主类加载到JVM。
类加载器的流程图如下:
其中loadClass的加载过程有一下几步:
加载 验证 准备 解析 初始化 使用 和卸载
1.加载 在硬盘上查找文件并通过IO获取文件字节码,采用懒加载的形式。即调用才加载。
在加载阶段会在内存中生成一个代表该类的String 对象 作为方法区这个类的各种数据的访问入口
2.验证 验证字节码文件的正确性
3.解析, 静态链接 如静态方法 main方法 等会在这个时候从符号引用转变成直接引用,动态链接是在程序中用到时才将符号转变成引用。
4. 初始化 对该类的静态变量和静态块进行运行
类被加载到方法区后主要包含 运行时常量池 类型信息 字段信息 方法信息 类加载器的引用 对应class实例的引用信息等。
类加载器的引用:这个类到类加载器实例的引用
对应class实例的引用 : 类加载器将类的信息加载到方法区后,会创建一个对应class类型的对象实例放到堆中,作为开发人员访问方法区中类定义的入口和切入点。
主类运行过程中如果使用到其他类 会逐步加载。
jar包和war包中的类也不是一次性加载的而是用到才加载。
下面写一段实例讲解:
public class TestLoad{
static{
//伪代码
sys.("static TestLoad ");
}
main(String [] args){
new A();
sys.(" main ")
//B在这里不会被加载除非new B()
B b=null;
}
class A{
static {
sys.(“static A”)
}
public A(){
sys.( "init A")
}
}
class B(){
static {
sys.(“static B”)
}
public B(){
sys.( "init B")
}
}
}
输出结果为:
static TestLoad
static A
init A
//这里可以看出 静态块是在构造方法的前执行的
main
下面说下类加载器的双亲委派机制:
首先需要知道java中的几种类加载器
1.引导加载器:负责加载用于支持JVM的位于jre lib目录下的核心类库,比如rt.jar等
由C++启动。
2.扩展类加载器:负责加载支撑JVM运行的位于jre lib 目录下 ext扩展目标下的jar包。
3.应用程序加载器:负责加载classpath下面的jar包,主要加载你自己写的(非jdk里面的都算)
4.自定义加载器:耐心看到本文介绍会有实例。
想要看某个类是哪个类加载器加载的 XXX.class.getClassLoader()方法。
下面看一组伪代码
sys(String.class.getClassLoader());
sys(com.sun.crypto.provider.DESkeyFactory.getClass().getClassLoader)
sys(ABC.class.getClassLoader());
null //因为这里内部是使用native 修饰调用的本地c++启动的 所以是null
sun.misc.Launcher$ExtClassLoader
sun.misc.Launcher$AppClassLoader
类加载器的初始化过程:
JVM的启动实例:sun.misc.Launcher 采用了单例模式设计。保证;了一个JVM只有一个 sun.misc.Launcher实例
在Launcher的构造方法中创建两个加载器实例分布是ExtClassLoader和AppClassLoader
JVM使用launcher的getClassLoader()返回类加载器实例AppClassLoader的实例加载我们的应用程序。
//launcher的构造方法
public Launcher(){
Launcher.ExtClassLoader var1;
try{
//构造扩展类加载器在构造过程中其父加载器设置为null
var1=Launcher.ExtClassLoader.getClassLoader(var1);
}catch(IOExeption){
throw new InternalError("xxx",var9);
}
Thread.currentThread().setContextClassLoader(this.loader);
String var2=System.getProperty("java.security.manager");
........
}
双亲委派机制 一句话就是先找老子加载 老子做不到就去求爷爷 爷爷也没有 就自力更生。再不行就死了。。
主要作用: 一个是沙箱安全机制 一个是避免类的重复加载。
我写累了 发现一个写的很好的文章。。。。。。。 内心无限mmp
https://blog.csdn.net/javazejian/article/details/73413292/?ops_request_misc=&request_id=&biz_id=102&utm_term=%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-73413292
开溜..............