JVM虚拟机模型
堆(heap)
在虚拟机启动的时候,堆就会被创建出来。可以通过相关参数来设置堆的大小等(例:-Xms:初始堆大小,-Xmx:最大堆大小,-Xmn:年轻代大小等)
堆是虚拟机中最大的一块内存区域,是线程共享的。
堆区又分为年轻代和老年代,其中,年轻代又分为Eden、s0、s1三部分,他们的默认比例为8:1:1
堆是GC(垃圾回收器)重点关注的对象。
如果heap不足,会抛出OutOfMemoryError异常
虚拟机栈(stack)
每一个虚拟机线程有一个虚拟机栈,栈是线程私有的内存区域,每个方法执行的时候都会在栈创建一个栈帧,方法的调用过程就对应着栈的入栈和出栈。
每个栈帧结构包含局部变量表、操作数栈、动态连接、方法返回地址。
局部变量表用于存储方法参数和局部变量。
操作数栈用于一些字节码指令从局部变量表中传递至操作数栈,也用来准备方法调用的参数以及接收方法返回结果。
动态连接用于将符号引用表示的方法转换为实际方法的直接引用。
方法区
方法区在逻辑上也属于堆,用来存储常量池、类的属性、方法数据、方法和构造方法的代码等
jvm只有一个方法区,被所有使线程共享
本地方法栈
主要用于执行本地native方法的区域
类加载机制
JVM类加载概念
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,就是虚拟机的类加载机制。
java类的生命周期
加载
加载字节码文件(.class)
1、通过全限定类名来获取定义此类的二进制字节流。
2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3、在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。
类加载器有三个:bootstrap(首要加载器):加载 jre/lib/目录下的核心类库
extension(扩展加载器):加载jre/lib/ext/目录下的类库
application:加载用户类路径ClassPath上所有的类库
三个加载器之间的关系:application继承于extension,extension继承于bootstrap
链接
确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
1、验证
(1)文件格式验证
如:是否以魔术0xCAFEBABE开头、主次版本号是否在当前虚拟机处理范围之内、常量合理性验证等。
(2)元数据验证
是否存在父类、父类的继承链是否正确
(3)字节码验证
通过数据流和控制流分析。确定程序语义是合法的、符合逻辑的
(4)符号引用验证
在解析阶段中发生,保证可以将符号引用转化为直接引用
2、准备
为类变量分配内存并设置类变量初始值
3、解析
虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化
执行类中定义的 Java 程序代码,此阶段是执行 () 方法的过程
使用
加载
双亲委派机制
工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。