2.认识JVM-类加载机制
目录
1.认识JVM之Classfile:https://www.cnblogs.com/nuti/p/16270652.html
2.认识JVM之类加载机制:https://www.cnblogs.com/nuti/p/16270672.html
3.认识JVM之运行时数据区: https://www.cnblogs.com/nuti/p/16270703.html
4.认识JVM之编译器: https://www.cnblogs.com/nuti/p/16270741.html
5.认识JVM之垃圾收集器: https://www.cnblogs.com/nuti/p/16270755.html
6.认识JVM之JVM内存模型: https://www.cnblogs.com/nuti/p/16270816.html
上文地址:https://www.cnblogs.com/nuti/p/16270652.html,接着往下说
这次到了ClassLoaderSubsystem
0.介绍引入
- 装载:
官网原文Loading is the process of finding the binary representation of a class or interface type with a particular name and creating a class or interface from that binary representation装载是查找具有特定名称的类或接口类型的二进制表示,并根据该二进制表示创建类或接口的过程。说人话就是把它加载到内存中
- 链接:
官网原文Linking is the process of taking a class or interface and combining it into the run-time state of the Java Virtual Machine so that it can be executed获取到的类或接口并将其组合到Java虚拟机的运行时状态以便执行的过程,说人话就是把java中的二进制的具体数据映射到内存空间的具体地址 这样cpu才能找到并且执行
- 初始化:
官网原文Initialization of a class or interface consists of executing the class or interface initialization method
1.Loading
1.1.几种类加载器
类加载无非就是找到class的全路径然后把它装载到内存中,java又是一门面向对象开发的语言,他这个过程肯定用到了 classLoader,这个过程中也会有很多class需要加载
一共有4种类加载器
- rt下面的交给bootstrap类加载器
- 扩展的交给Extension类加载器
- classptah下的指定的包交给App类加载器
- 自定义的则交给custom类加载器
假设一种前提?我自己在业务代码中写了一个classpath写了一个java.lang.string 如果这样的话 岂不是app中和bootstrap中都要加载一番?
其实不会 那么就引入下面的双亲委派机制
2.1.双亲委派机制
检查类是否加载?
检查某个类是否加载 他会从下到上 custom classLoader到BootstrapClassLoader开始逐层检查,只要是某个classLoader加载过了就被看作已经加载过这个类,保证此类只会加载一次
那么由此可见加载器的调用顺序 就是自上而下,由上层来逐层尝试加载此类
打开ClassLoader源码找到loadClass方法,
看到源码中判断父类是否为空 不为空去父类上去看
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } //-----下面省略
测试一下
那么这样问题又来了,这样一步步去寻找肯定会很消耗性能,那么确定只有一种情况下不需要别的加载器再来参与的前提下,直接指定类加载器呢?
2.2.打破双亲委派
打破双亲委派方式
- 复写loadClass
- spi机制
- Osgi
- ...
2.Lingking
打开官网的lingking就可以发现还有3个小步骤
- Verification:验证类的正确性
- Preparation:准备为类或者接口的静态字段赋值为默认值
Preparation involves creating the static fields for a class or interface and initializing such fields to their default values例子:private static int a = 10;这个时候 准备阶段只是会给你附上一个默认值为0
- Resolution:解析 动态的将运行时常量池中的符号引用转换为直接引用
Resolution is the process of dynamically determining concrete values from symbolic references in the run-time constant pool
3.initializing
Initialization of a class or interface consists of executing its class or interface initialization method
还是上面的那个例子,上面给了一个默认值为0 这里就真正的吧10给了a private static int a = 10