一、JVM 是 Java Virtual Machine 的缩写,它是一个虚构出来的计算机,一种规范。通过在实际的计算机上仿真模拟各类计算机功能实现···
简单来说其实就类似于一台小电脑运行在windows或者linux这些操作系统环境下,它直接和操作系统进行交互,与硬件不直接交互,可操作系统可以帮我们完成和硬件进行交互的工作。
JVM 是不认识文本文件的,所以它需要进行编译 ,让其成为一个它会读二进制文件的 HelloWorld.class 。
1.类加载器 JVM执行.class文件,需要先把文件放到一个类加载器中。类加载器会把所有的 .class 文件全部搬进JVM里面来。
2.方法区 是用于存放类似于元数据信息方面的数据的,比如类信息,常量,静态变量,编译后代码···等。(.class相关信息)
3.堆 主要放了一些存储的数据,比如对象实例,数组···等,它和方法区都同属于 线程共享区域 。也就是说它们都是 线程不安全 的。(new出来内容)
4.栈 这是我们的代码运行空间。我们编写的每一个方法都会放到 栈 里面运行。存放方法中的变量以及方法在栈中运行。(栈管运行,堆管存储)(先进后出,后进先出)
5.程序计数器 主要就是完成一个加载工作,类似于一个指针一样的,指向下一行我们需要执行的代码。和栈一样,都是 线程独享 的,就是说每一个线程都会有自己对应的一块区域而不会存在并发和多线程的问题。
总结:虚拟机主要的5大块:方法区,堆都为线程共享区域,有线程安全问题,栈和本地方法栈和计数器都是独享区域,不存在线程安全问题,而 JVM 的调优主要就是围绕堆,栈两大块进行。
二、类加载器的介绍
类加到虚拟机的流程:加载,验证,准备,解析,初始化,使用,卸载。其中验证,准备,解析三个部分统称为连接。
2.1 加载
- 将class文件加载到内存。
- 将静态数据结构转化成方法区中运行时的数据结构。
- 在堆中生成一个代表这个类的 java.lang.Class对象作为数据访问的入口。
2.2 链接
- 验证:确保加载的类符合 JVM 规范和安全,保证被校验类的方法在运行时不会做出危害虚拟机的事件,其实就是一个安全检查.
- 准备:为static变量在方法区中分配内存空间,设置变量的初始值,
例如 static int a = 3 (注意:准备阶段只设置类中的静态变量(方法区中),不包括实例变量(堆内存中),实例变量是对象初始化时赋值的) - 解析:虚拟机将常量池内的符号引用替换为直接引用的过程(符号引用比如我现在import java.util.ArrayList这就算符号引用,直接引用就是指针或者对象地址,注意引用对象一定是在内存进行)
2.3 初始化
初始化其实就是一个赋值的操作,它会执行一个类构造器的<clinit>()方法。由编译器自动收集类中所有变量的赋值动作,此时准备阶段时的那个 static int a = 3 的例子,在这个时候就正式赋值为3。
2.4 卸载
GC将无用对象从内存中卸载。
类加载器的加载顺序
加载一个Class类的顺序也是有优先级的,类加载器从最底层开始往上的顺序是这样的。
- BootStrap ClassLoader:rt.jar
- Extention ClassLoader: 加载扩展的jar包
- App ClassLoader:指定的classpath下面的jar包
- Custom ClassLoader:自定义的类加载器