JVM从入门到精通-类加载子系统

第2章:类加载子系统

class文件通过类加载器子系统加载进内存中,执行引擎根据字节码指令依次执行

类加载:加载阶段--链接阶段--初始化阶段

方法区:存放常量,域信息,方法信息;只有hospot有其他JVM没有;

执行引擎:解释器,JIT即时编译器,分析其,垃圾回收器;

类加载器和执行引擎

类加载器:获取类的信息并装进内存

执行引擎:逐条解释指令

2.1概述类的加载器及类加载过程

类加载器子系统作用

image-20200620122921795

  • 类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识(魔数)
  • 类加载器ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。
  • 加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)

方法区:类信息,运行时常量池信息,字符串字面量,数字常量;

1.类加载器子系统从文件中读取.class文件加载进内存中并生成Class对象

2.在字节码反编译后可以看到Constant pool(常量池),加载进内存中称为运行时常量池

2.2类加载器ClassLoader角色

image-20200620124457898

  1. class file 存在于本地硬盘上,可以理解为设计师画在纸上的模板,而最终这个模板在执行的时候是要加载到JVM当中来根据这个文件实例化出n个一模一样的实例。
  2. class file 加载到JVM中,被称为DNA元数据模板,放在方法区
  3. 在.class文件-> JVM ->最终成为元数据模板,此过程就要一个运输工具(类装载器 Class Loader), 扮演一个快递员的角色

getClass获得类本身

2.3类的加载过程

image-20200620124817940

类加载过程:加载(Loading)、链接(Linking){验证(Verification)、准备(Preparation)、解析(Resolution)}、初始化(Initialization)

2.3.1类的加载过程简单案例:

public class HelloLoader {
    public static void main(String[] args) {
        System.out.println("谢谢ClassLoader加载我....");
        System.out.println("你的大恩大德,我下辈子再报! ");
    }
}
当执行HelloLoader的main方法时,过程如图:

1.类加载(Loading)

1.通过一个类的全限定名获取定义此类的二进制字节流;

2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

3.在内存中生成一个代表这个类的java.lang.Class对象(大的Class对象),作为方法区这个类的各种数据的访问入口

å¨è¿éæå¥å¾çæè¿°

总结:生成大的Class文件是在Loading阶段

2.链接(Linking)

å¨è¿éæå¥å¾çæè¿°

链接三个阶段:验证-准备-解析

Binary Viewer(二进制文件查看器)

验证:class文件开头时CAFEBABE(魔数)

准备:为变量分配默认初始值

反编译查看:

java -p HelloApp.class

3.初始化Initialization

å¨è¿éæå¥å¾çæè¿°

注意:clinit就是类的构造器

clinit会自动赋值:将类中所有类变量的赋值动作和静态代码块的语句合并起来;

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

因为定义在后面,所以前面不能调用;

å¨è¿éæå¥å¾çæè¿°

若有父类,先调用父类的clinit构造器;A=2

JVM保证类的clinit方法多线程同步锁;即构造器只会调用一次;

2.4 类加载器分类

å¨è¿éæå¥å¾çæè¿°

JVM分两种类型的类加载器:引导类加载器(Bootstrap ClassLoader)、自定义类加载器(User-Defined ClassLoader)

å¨è¿éæå¥å¾çæè¿°

JVM将所有派生于抽象类ClassLoader(间接继承)的类加载器都划分为自定义加载器;

å¨è¿éæå¥å¾çæè¿°

虚拟机子带类加载器

扩展类加载器

应用程序类加载器

å¨è¿éæå¥å¾çæè¿°

程序

启动类加载器:无法获得父类;

扩展类加载器、应用类加载器:可以获得父类;

用户自定义类加载器

å¨è¿éæå¥å¾çæè¿°

用户自定义类加载器步骤

读入字节流;

关于ClassLoader

说明:只要继承ClassLoader都是基于JAVA编写的;引导类加载器是C++编写的,所以不能继承;

下图说明扩展类和应用类都继承自ClassLoader

获取ClassLoader的几种方法

双亲委派机制

例子:

未使用自定义的类,还是使用核心类

向上委托:自定义类加载器Custom ClassLoader---系统类加载器Application ClassLoader--拓展类加载器Extension ClassLoader--引导类加载器Bootstrap Classloader


 

接口的实现需要第三方的Jar包;不在核心API内,所以反向委托-线程上下文类加载器ContextClassLoader;调用系统类加载器AppClassLoader;

下面说明不能加载java.lang包,会报包访问安全冲突

沙箱安全机制

双亲委派机制:一直委派到父类,父类加载核心String类中没有main方法;所以报错;不会加载自定义的类;

类的主动使用和被动使用

两个Class对象相同:

类的完整类名必须一致,包括包名;

加载这个类的ClassLoader必须相同

对类加载器的引用

类的主动使用和被动使用

区别在于:是否初始化;加载-链接-初始化;被动使用是不进行类的初始化,不执行clinit,静态代码块等;

猜你喜欢

转载自blog.csdn.net/syc0616/article/details/113750891