一文带你理解JVM原理

410 阅读3分钟

JVM

基本概念

JVM(JAVA virtual Machine)是可以运行Java代码的假想计算机,他是运行在操作系统上的。每一种平台的解释器不同,但是实现的虚拟机是相同的,这也就是Java为什么能够跨平台的原因了。

线程

JVM允许一个应用并发执行多个线程。当线程本地储存,缓冲区分配,栈,程序计数器准备好后,就会创建一个操作系统原生线程。Java线程结束,原生线程随之被回收, 同时释放所有相关资源。

JVM 内存区域

线程私有

生命周期与线程相同,用户线程启动/结束,而创建/销毁

程序计数器 Program Counter Register

  • 一块较小的内存空间,每个线程都有一个独立的程序计数器,在这里记录的是虚拟机字节码指令的地址(即当前指令的地址)

虚拟机栈 VM Stack

  • 每个方法在执行时都会创建一个栈帧(Stack Frame)用于储存局部变量表,操作数栈,动态链接,方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程
  • 栈帧随着方法调用而创建,随着方法结束而销毁,无论方法时正常完成还是异常完成都算作方法结束

本地方法栈 Native Method Stack

  • 和虚拟机栈类似,区别为虚拟机栈为Java方法服务,而本地方法栈为Native方法服务

线程共享

线程共享区随虚拟机的启动/关闭,而创建/销毁

堆 Heap

  • 保存所有创建的对象,数组
  • 垃圾收集器进行的最重要内存区域

方法区/永久代 Method Area

  • 保存所有被JVM加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
  • 运行时常量池 Runtime Constant Pool也是方法区的一部分,用于存放编译期生成的各种字面量和符号引用

JVM 运行时内存

新生代

新生代一般用来存放新生的对象,占据堆1/3的空间,会频繁触发MinorGC。

MinorGC采用复制算法,首先把eden,survivorFrom的存活对象复制到survivorTo区,再把他们的年龄+1。接下来清空eden,survivorFrom中的对象,并把survivorTo 和 survivorFrom互换,原survivorTo内的对象会成为下一次GC的survivorFrom区。

Eden

  • Java新对象的出生地,当这个区域内存不够时就会触发MinorGC

SurvivorFrom

  • 上一次GC的幸存者,这一次GC的被扫描者

SurvivorTo

  • 保留了一次MinorGC过程中的幸存者

老年代

老年代对象稳定,一般在执行MajorGC前都会进行一次MinorGC。 MajorGC采用标记清除算法,扫面所有对象,标记存活对象后回收所有没有标记的对象。

永久代

GC不会在主程序运行期间对永久区进行清理,所以可能出现随着加载class的增多而抛出OOM异常的状况

元数据

JAVA8中,永久代已经移除,被元数据区取代。他并不在虚拟机中,而是使用本地内存。这样,元数据区的大小仅受本地内存限制