1. JVM是什么
JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。
2. JVM内存布局详细介绍一下
虚拟机栈、本地方法栈、程序计数器(线程私有的)
方法区、堆(线程共享的)
- 方法区:被所有线程共享区域,用于存放已被虚拟机加载的类信息,常量,静态变量等数据。被Java虚拟机描述为堆的一个逻辑部分。习惯叫它永久代。
垃圾回收很少光顾这个区域,不过也是需要回收的,主要针对常量池回收,类型卸载。
常量池用于存放编译期生成的各种字节码和符号引用,常量池具有一定的动态性,里面可以存放编译期生成的常量;运行期间的常量也可以添加进入常量池中,比如string的intern()方法。 - 堆:Java堆是线程共享的内存区域,在虚拟机启动时创建,它的唯一目的是存放对象实例。Java堆是垃圾收集器管理的主要区域,也被称为GC堆,通常情况下分为两个区块年轻代和年老代。
- Java堆可以处在物理上不连续的内存空间中,只要逻辑上是连续的即可。空间不足时抛出内存溢出异常。
方法区和堆:会有OutOfMemoneyError - 虚拟机栈:每个方法在执行时都会创建一个帧栈,用于存储局部变量、操作数栈等信息,每一个方法从调用到执行完成,对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。是线程私有的,生命周期与线程相同。
- 本地方法栈:也是线程私有的。虚拟机栈为虚拟机执行的Java方法服务,而本地方法栈为虚拟机使用的本地方法服务。
虚拟机栈和本地方法栈:当线程请求栈深度大于虚拟机所允许的深度就会抛出StackOverFlowError错误;虚拟机栈动态扩展,当扩展无法申请到足够的内存空间时候,抛出OutOfMemoneyError。
- 程序计数器:记录线程执行到的字节码行号,为了使线程切换后能恢复到正确的执行位置,每条线程都有一个独立的程序计数器,互不影响,独立存储,所以这块内存区域是线程私有的。 此区域是唯一 一个虚拟机规范中没有规定任何内存溢出情况的区域。(OutOfMemoryError,即 OOM) 。
JVM发生OOM的四种情况?
- Java堆溢出
- 方法区溢出
- 栈溢出
- 运行时常量溢出