JVM定义
Java Virtual Machine :Java虚拟机
类加载机制
类加载三步骤:装载(Load)–链接(Link)–初始化(Initialize)
- 装载:查找和导入.class文件
- 通过类的全限定名获取定义此类的二进制字节流。
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构(类信息+常量)。
- 在堆中生成一个代表这个类的java.lang.class对象,作为方法区这些数据的访问入口。
- 链接
- 验证–保证被加载类的正确性
- 准备–为类的静态变量分配内存,并将其初始化为默认值
- 解析–把类中的符号引用转化为直接引用
- 初始化
对类的静态变量,静态代码块执行初始化操作。
类加载器
在装载阶段,通过类的全限定名获取其定义的二进制字节流,需要借助类加载器来完成。
类加载器加载原理
- 检查:检查某个类是否加载,检查的顺序是自底向上,只要某个ClassLoader已经加载,就视为已加载,保证一个类只能被CassLoader加载一次。
- 加载:加载顺序是自顶向下,由顶层逐层尝试加载此类。
双亲委派机制
- 定义:如果一个类加载器在接收到加载请求时,它首先不会尝试去加载这个类,而是把这个请求任务交给自己的父类去完成,依次递归,如果父类可以完成这个类的加载,就成功返回;如果父类不能完成,才自己去加载。
- 破坏双亲委派机制:自定义类继承ClassLoader类,并重写LoadClass方法
JVM运行时数据区
- 方法区
- 方法区是各个线程共享的区域,在虚拟机启动时候创建。
- 用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
- 当方法区无法满足内存分配时,就会抛出OutOfMemoryError。
- 方法区在jdk8中是Metaspace
- 运行时常量池–>runtime constant pool 从方法中单独开辟的一部分空间,存放编译时期生成的字面量以及符号引用。
- 堆
- 堆是Java虚拟机管理内存的最大的一块,在虚拟机启动时候就创建,为线程共享的。
- Java对象实例以及数组都在堆中分配。
- 虚拟机栈
- 虚拟机栈是一个线程的执行区域,保存着一个线程中方法的调用状态;即一个Java线程的运行状态,由虚拟机栈来保存。
- 虚拟机栈是线程私有的,随着线程的创建而创建。
- 每个线程执行的方法,为该栈的栈帧,即每个方法对应一个栈帧。调用一个方法,就会向栈中压入一个栈帧,一个方法调用完成,就会把栈帧从栈中弹出。
- 本地方法栈
如果当前线程的方式是native类型,这些方法就会在本地方法栈中执行。
- 程序计数器
保证线程切换后能够恢复到正确的位置,每个线程需要有一个独立的程序计数器,即该区域为线程私有的。