--- jvm中一个类的一生 ---

发布于:2025-02-17 ⋅ 阅读:(130) ⋅ 点赞:(0)

当一个类被加载到jvm中使用,类会经过这些过程

加载 --> 连接--> 初始化 --> 使用 --> 卸载   这就当程序运行起来后,一个类在jvm中的一生

其中类加载是在 加载 --> 连接--> 初始化 这三个阶段  在这个之中 连接又能细分为3个阶段 

验证 --> 准备 --> 解析

所以类加载的实际过程是

加载 --> 验证 --> 准备 --> 解析 --> 初始化

现在来一一解释下这写过程会发生什么

加载

会通过类的全限定名(java.util.list这就是List类的全限定名)查找到这个类,并获得他的二进制字节流,通过字节流将这个类的静态储存结构转换为方法区的运行时数据结构,并在内存中生成一个java.lang.class的文件,作为方法区中这个类的各种数据的访问入口,在查找这个类的时候会涉及到双亲委派模型

验证

校验这个类是否符合jvm的规范,防止在jvm中运行可能有安全问题

准备

给这个类中的变量开辟全0的空间(static修饰的)但是没有赋值,所以这时我们的静态变量就已经创建出来了

解析

解析阶段是将变量的字符引用改为直接引用,这里的字符引用指的是通过全限定名来指向变量,比如类的全限定名 java.util.list 字段的全限定名 java.util.list.size这种,该为直接引用,直接用对应的空间地址来指向变量,而且上一步正好还为变了赋给了空间,这样效率跟高,在使用时不用根据全限定名查找

初始化

针对所有静态成员的属性填充,比如有 static int i = 1,在初始化之前,i为0,初始化之后就为1了

初始化之后,这个类就被加载到jvm的方法区中了

在类加载结束之后 剩下俩个 使用 和 卸载就很简单了

使用 就是通过代码对这个类的使用,卸载,在这个类不会在使用之后,通过gc来将这个类释放,返回资源

双亲委派模型

之前在加载的时候提到了双亲委派模型,指得是,在jvm中又三个类加载器

BootstrapClassLoader (标准库)   ExtensionClassLoader(扩展库)   ApplicationClassLoader (第三方库 /自己的项目)

他们在加载类的时候,会以ApplicationClassLoader这个加载器作为入口,但是他不会立刻在他这里寻找类,而是将这个任务委托给他的父类ExtensionClassLoader,他也不会立刻寻找,也是会将这个任务委托给他的父类BootstrapClassLoader,BootstrapClassLoader没有父类了,那么他就会开始寻找这个类,如果找到了的话,就直接加载这个类,没找到的话就返回任务给他的子类ExtensionClassLoader,他也没找到就继续往下递给ApplicationClassLoader,最后如果都没找打哦,那就抛出异常,ClassNotFound,如果加载类有父类,那么还会执行他父类类的类加载

双亲委派模型确保了都是最先从标准库中加载的,且确保了一个类只会被加载一次,比如有类A 有类B,他们都有相同父类C,在加载A的时候,会加载父类C,而在加载B的时候,发现父类已经被加载并缓存了,那么就会直接返回这个加载好的父类C,而且也不出现不同加载器加载了同一个类名的情况,因为每次加载的路径相同

over--


网站公告

今日签到

点亮在社区的每一天
去签到