Java虚拟机

Java内存管理机制

JVM有哪些分区,要求画图,并作出详细说明——答案有待进一步细化完善?

  • 程序计数器
程序计数器-线程私有,指向下一条需要执行的字节码指令
程序计数器是Java虚拟机规范中唯一没有规定OutOfMemoryError异常的区域
  • Java虚拟机栈
Java虚拟机栈-线程私有,生命周期与线程相同,Java虚拟机栈描述的是Java方法执行的内存模型;
每个方法在执行的同时都会创建一个栈帧,栈帧用于存放局部变量表,操作数栈,动态链接,方法出口等信息;
局部变量表存放编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double),对象引用,returnAddress类型
64位长度的long和double类型占用2个局部变量空间,其余的数据类型占用一个局部变量空间
局部变量表所需的内存空间在编译期间分配完成,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是确定的,在方法运行期间不会改变局部变量表的大小
每个方法从调用直至执行完成的过程,就对应着栈帧在虚拟机栈中从入栈到出栈的过程;

Java虚拟机栈中规定了两种异常情况:
	如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
	如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存,将抛出OutOfMemoryError异常
  • 本地方法栈
Java虚拟机栈为虚拟机执行的Java方法服务,而本地方法栈为虚拟机执行的本地方法服务

本地方法栈规定两种异常情况(原理参考虚拟机栈):
	StackOverflowError异常
	OutOfMemory异常
Java堆——线程共享,存储对象实例及数组
Java虚拟机展栈——存储基本数据类型,对象引用,returnAddress类型

Java堆中规定的异常
	如果在堆中没有实例完成内存分配,并且堆也无法再扩展时,将抛出OutOfMemoryError异常
  • 方法区
方法区——线程共享,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等

方法区中最重要的是运行时常量池。
运行时常量池——存放编译期生成的各种字面量和符号引用,直接引用
运行时常量池——可在运行期间向运行时常量池中添加常量,String.intern()
Class文件常量池——普通常量池,无法在运行期间添加常量

方法区规定的异常:
	当方法区无法满足内存分配需求时,将抛出OutOfMemory异常
	当运行时常量池无法再申请到内存时,将抛出OutOfMemory异常

OutOfMemory异常的发生场景

1. 程序计数器是唯一一个在Java虚拟机规范中没有规定任何OOM情况的区域
2. 在Java虚拟机规范中,对于Java虚拟机栈,规定了两种异常:
	1) 若线程请求的栈深度 > 虚拟机所允许的深度,则抛出StackOverflowError异常
	2) 若虚拟机可以动态扩展,若扩展时无法申请到足够的内存空间,则抛出OOM异常
3. Java虚拟机栈执行java方法,本地方法栈为虚拟机使用native方法服务,本地方法栈也会抛出StackOverflowError和OOM
4. Java堆可以处于物理上不连续的内存空间,只要逻辑上是连续的即可。可固定,可扩展。若堆中没有内存完成实例分配,并且堆也无法再扩展,则会抛出OOM
5. 直接内存不是运行时数据区的一部分

垃圾回收机制

JVM中如何判断一个对象是否存活?

引用计数算法

缺点:很难解决对象之间循环引用的问题

可达性分析算法

  • 基本思想
通过一系列的“GC roots”的对象作为起始点,从这些节点,开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC root没有任何引用链相连(用图论的话来说,就是从GC roots到这个对象不可达),则证明此对象是不可用的

引用强度强引用 > 软引用 > 弱引用 > 虚引用

  • 可达性分析法对象回收过程
	若对象在进行可达性分析后发现没有与GC roots相连接的引用链,那么它将会被第一次标记并进行一次筛选,筛选的条件是该对象是否有必要执行finalize()方法,当对象没有重写finalize()方法或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为没必要执行
	若该对象被判定为有必要执行finalize()方法,则这个对象会被放在一个F-Queue队列,finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行一次小规模的标记,若对象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,那么在第二次标记时他们将会被移出"即将回收"集合

finalize()不是C或C++的析构函数
  • 可以作为GC roots的对象
1. Java虚拟机栈中引用的对象(栈帧中的本地变量表)
2. 方法区中类的静态属性引用的对象
3. 方法区中常量引用的对象
4. 本地方法栈中JNI引用的对象

JVM有哪些垃圾回收算法,并作出详细说明?

  • 标记-清除算法
  • 停止-复制算法
  • 标记-整理算法
  • 分代收集算法

JVM中各引用的强度比较?

说说JVM的类加载机制?

12-25 04:21