Java与JVM(Java Virtual Machine 简称:Java虚拟机)
Java与JVM
JVM运行时数据区
线程共享: 所有线程能访问这块内存数据,随虚拟机或者GC而创建和销毁。
线程独占: 每个线程都会有它独立的空间,随线程生命周期而创建和销毁。
方法区
作用:存储加载类信息,常量,变量,JIT编译后的代码等数据.
GC:
- 方法区的垃圾回收,但回收效率低
- 回收主要针对常量池,和类型的卸载
- 当方法去无法满足内存的时候,报OOM.
堆内存
作用:存在对象实例,几乎所有的对象,数组都在这里存放
- 对于大多数应用来说,堆是JVM管理的内存中最大的一块内存区域,也是最容易OOM的区域
- 大多数JVM都将堆实现为大小可扩展的,(通过-Xmx、-Xms控制)
live or die
引用计数器算法,存在两个对象相互引用的问题 .
可达性分析算法:
主流的商用程序语言(Java、C#)都是通过可达性分析算法来判定对象是否 存活的,GC Roots可以是:
- 虚拟机栈。
- 方法中静态属性引用的对象。
- 方法区中常量引用的对象。
- Native方法引用的对象。
虚拟机栈
虚拟机栈:
线程中方法执行的模型,每个方法执行时,就会在虚拟机栈中创建一个栈帧, 每个方法从调用到执行的过程,就对应着栈帧在虚拟机栈中从入栈到出栈的过程。
栈帧:虚拟机栈由多个栈帧(Stack Fframe)组成。一个线程会执行一个或多个方法, 一个方法对应一个栈帧。
本地方法栈
本地方法栈:
- 和虚拟机栈功能类似,虚拟机栈是为虚拟机执行JAVA方法而准备的, 本地方法栈是为虚拟机使用Native本地方法而准的。
- 《Java虚拟机规范》中对Native方法使用的语言、使用方式与数据结构没有强制规定。
- HotSpot虚拟机中虚拟机栈和本地方法栈合二为一。
程序计数器
程序计数器(Program Counter Register)记录当前线程执行字节码的位置,字节码解释器 工作时,就是通过改变计数器的值来选取下一条需要执行的字节码指令。
- 如果执行java方法,存储的是字节码指令地址,如果执行Native方法,则计数器值为空。
- 程序计数器是唯一一个在《JVM规范》中没有任何OOM的区域
直接内存 (不属于JVM内存区的)
直接内存不是JVM运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域, 是我们常说的堆外内存。
- JDK1.4 引入NIO,它可以使用Native函数库直接分配堆外内存,然后通过一个存在在Java堆 中的DirectByteBuffer对象作为操作这块内存区域的引用进行操作。
- 直接内存不受Java堆大小限制,当内存总和大于机器物理内存时,会OOM。