jvm 体系结构学习
jvm体系结构
类装载器 --- > (运行时数据区:方法区,堆,java栈,pc寄存器,本地方法栈) --- > 执行引擎 --- > 本地方法接口 < --- 本地方法库
装载
--- |-- 如何装载一个类,如何解析
|-- 启动类装载器, 用户自定义装载器
|-- 每个类装载器都有自己的命名空间,维护着由他装载的类型
|-- 关于类装载的详细细节,后面介绍.tbt
方法区,堆,栈,寄存器,本地方法栈
方法区
---
|-- 方法区中的数据必须是线程安全的。
|-- 方法区中需要使用合理的数据结构以保证以保证虚拟机查找其中的类型信息。
|-- 方法区可以被垃圾收集。
|-- 方法区的大小不是固定的,可以在堆中自由分配
|-- 方法区中存储的类型信息
|-- 类型的全限定名
|-- 这个类型的超类的全限定名
|-- 类类型还是接口类型
|-- 类型的访问修饰符
|-- 超接口的全限定名?
|-- 类型的常量池
|-- 字段信息
|-- 方法信息 -- 方法的字节码,方法的栈帧中的局部变量区的大小,异常表
|-- 静态变量
|-- 类到classloader的引用,当该类被引用时,该类的classloader被请求装载该类。
|-- 类到Class的引用
|-- 编译时常量 ,每个使用编译时常量的类型都会复制他的所有常量到自己的变量池中
|-- 方法表,方法表示一个数组,保存了所有实例方法的引用
堆,栈
---
|-- 每个虚拟机实例拥有一个 所有线程共享的方法区和堆
|-- 方法区中放着所有装载的类的信息
|-- 堆中放着所有的对象
|-- 每个线程拥有自己个pc寄存器和栈
|-- 对于本地方法, 存储在本地方法栈中
|--
|--栈有很多栈帧组成,一个栈帧包含一个Java方法调用的状态
|--栈帧
|--由三部分组成,局部变量区,操作数栈,帧数据区。
|-- 局部变量区和操作数栈在编译时确定
|-- 操作数栈就是各种命令了。加减乘除
|-- 帧数据用来解析常量池,正常方法返回,异常机制。在正常返回的情况下,虚拟机必须恢复发起调用前的方法的栈帧,设置pc寄存器指
向发起调用的方法中的指令。如果有返回值,虚拟机必须将其压入调用方法所在的操作数帧。
|--每个线程拥有独立的栈
|-- 每次调用方法,一个新的栈帧会压入该线程的java栈中。
|-- 堆栈区别, 堆是动态分配内存,生存周期不用事先声明,垃圾收集齐自动收集
|-- 栈的存取速度快,可以共享数据,生存期确定?(确定为何意)
|-- 栈中主要存放一些基本类型的变量
|-- 堆中数据的垃圾收集
|--
|-- 堆的设计,堆中的对象必须可以引用到方法区中的信息,必须可以引用到堆中的其他的类变量信息。
|-- 一种设计方案:一个句柄包含 指向方法区类型信息的引用,包含指向堆中类变量信息的引用。
|-- 另一种,一个句柄包含所有的类变量信息,同时包含指向方法区中类信息的引用。
-- 方法区中的类信息
|--方法表,一个一个指向方法数据的指针,指向类其他所有数据的指针
|-- 因为程序中调用某个实例方法时,虚拟机必须进行动态绑定。虚拟机必须根据对象的实际类,所以虚拟机必须通过对象的引用来访问类数据。
执行引擎
---
|--
虚拟机内部进程:守护进程,非守护进程
java数据类型
基本类型,引用类型
---
|--数值类型:浮点float, double
|--整数类型:byte, short, int, long, char
|--boolean, returnAddress
|-- 引用类型: 类类型,接口类型,数组类型
装载类过程
---
|-- 虚拟机读入对应类的字节码,提取信息并放在方法区中。
|-- 执行保存在方法去中的字节码,开始执行main()方法,此时虚拟机会一直持有当前类的常量池的指针。
|-- 当后面发现对该类的引用时,虚拟机去查找方法区,看该类是否已经被装载,如果没有装载则装载,
|-- 装载后,虚拟机将本来指向其常量池的指针替换为执行该类方法区类数据的指针。
|-- 此时才开始为该类分配内存。虚拟机获得该类类型信息,获得一个该类对象需要分配多少堆空间。然后开始各种初始化。
|-- 然后执行,将该类压入堆栈,继续执行下一条命令。