引言
这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
一直以来,我是致力于传播正能量的,我写文章就用我自己的风格,自己的思路,不去随和、抄袭、迎合别人,我以事实为依据,在我能力范围叙述我的能力故事,我觉得能做到这一点就很好了,如果写出的文章不趁人意,那我也没有办法,努力去做就好了。
我们今天来介绍一下JVM的类加载技术,读完本篇文章你会了解类的生命周期,类的加载过程是如何从虚拟机开始的,整个流程是什么样的,至于有什么作用各位自己体会。
类的启动
关于类的启动,规范中是这样进行描述的:虚拟机初始和启动一个类是通过启动类加载器来指定初始类的启动的,(当前规范的版本是java8),然后链接和初始化该类,之后会调用公共方法main方法,也就是我们程序的入口,来拉动整个程序的运行。
对于初始类的选择呢,你要么作为参数就行提供,要么自己实现,并提供一个类加载器,使用该类加载器加载此应用,当然,其它选择也是可以的,只要你符合上述规范。
类的生命周期
类的生命周期也是老生长谈的话题:加载、验证、准备、解析、初始化、使用、卸载,下面我们分别聊一下:
- 加载:找字节流,说白了就是找到我们的Class文件。
- 验证:看看类文件是不是符合解析格式
- 准备:为被加载类的静态字段分配内存
- 解析:把符号引用,解析成实际引用。
- 初始化:主要是初始化构造方法
类或接口的创建
这里说了类和接口的创建需要在方法区创建一个与之相匹配的内部表示,一个类或接口的创建是由另一个类或接口进行触发的,当然我们还可以通过java提供的类库触发,比如反射。
java的类库如下:
- Reflection, such as the classes in the package
java.lang.reflect
and the classClass
. - Loading and creation of a class or interface. The most obvious example is the class
ClassLoader
. - Linking and initialization of a class or interface. The example classes cited above fall into this category as well.
- Security, such as the classes in the package
java.security
and other classes such asSecurityManager
. - Multithreading, such as the class
Thread
. - Weak references, such as the classes in the package
java.lang.ref
.
然后,看这个类是不是数组类,如果不是数组类,那就使用类加载器进行加载它的二进制表示。
类加载器
类加载器种类
关于类加载器呢,一共有这么三种:启动类加载器,扩展类加载器,和应用类加载器。
启动类加载器加载java的核心库,比如jre下的rt.jar包,扩展类加载器呢,加载的是lib目录下ext下的包,剩下的就由我们的应用类加载器进行加载,比如我们自己定义的类。
此外,我们还可以自定义类加载器,用于加载一些特定的类。
java虚拟机支持两种类加载器:java虚拟机提供的启动类加载器和用户自定义的类加载器,每个用户自定义的类加载器都应该是抽象类Classloader的某个子类的实例。给用户提供自己定义的类加载器是为了便于扩展java虚拟机的功能,以支持动态加载并创建类。
类加载器的加载机制
关于类加载器的加载机制,无非是为了确保一个类只加载一次,看看规范是怎么说的,对于C的创建,你可以自己搞或者委托其他类加载器帮你搞,如果是你自己搞的,那就说明该类是你定义和创建的。
如果你把加载请求委托出去了,说明该类不是你直接定义的,这时可以说该类是你初始化创建的。可以看出规范说是可以委托,具体怎么委托并没有提到,那就由自己内部进行实现。
我们接着往下看:如果类是由(bootstrap 加载器)启动类加载器所定义的,那么用启动类加载器加载,如果是用户定义的,那就用户定义的类加载器加载,如果N是一个数组类,那么该数组类是由java虚拟机而不是类加载器创建的。
本文转载自: 掘金