JVM内存分区

JVM是一种用于计算设备的规范,通过在实际的计算机上仿真模拟各种计算机功能来实现的。

JVM内存分区

线程共享

堆heap

用于所有对象实例(包括数组),也是GC管理的主要区域,并且可以要求分配的地址不是物理连续的,只要逻辑连续即可
堆可更详细的分为下面几个区域

青年代 youngGeneration

青年带又具体分为

  • Eden区
    新生对象首先分配在Eden区,如果内存不够,发起一次Minor GC。是整个heap区中占比最大的
  • From Survivor区
    约为Eden的18\frac 18。如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,知道达到阀值对象进入老年区
  • To Survivor区

老年代oldGeneration

大对象将直接建立在老年代中,此外Survivor区中对象存活年龄到达阈值也将进入老年区

关于对象在heap中的生命流程将在另一篇详细说明

该位置抛出OOM(OutOfMenory Error)

方法区

用于存储已被虚拟机加载的类信息常量,静态变量,即时编译器编译后的代码等数据。
实现方法之前是永久代 PermGen,现在替换为元空间 MetaSpace

为什么将PerGen替换为MetaSpace?
PermGen又JVM自身设置的固定上限,而MetaSpace直接使用系统内存,减少溢出的产生

关于方法区存储的类信息,详见: ʅ(´◔౪◔)ʃ
关于常量池和运行时常量池介绍见 ◐▽◑

同样该区域会抛出OOM

线程独享

程序计数器

当前线程所执行字节码的行号指示器

多线程切换后复原实现:
线程轮流切换,分配处理器时间。因而为了能使切换后继续执行而不至于从头来过,因此每个线程独立的程序计数器保存切换前的最后一条指令,在切换回来之后读取继续执行

JVM栈

java程序从启动到结束,实际就是main函数从入栈到出栈的过程,所以在说明JVM栈之前先讲解JVM栈的基本单位,Java方法执行的内存模型:

栈帧

JVM内存分区
其中局部变量表所占内存在编译器决定,运行期不会再改动。这里解释了为什么使用多态接受对象时,不能调用子类方法。

这里会抛出两个异常,一个是内存不够抛出的OOM,还有栈深度超过限制抛出的StackOverflow Error

native方法栈

与JVM栈的作用非常相似,区别是:虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法。


参考资料:

  1. JVM内存划分
  2. 24个Jvm面试题总结及答案
  3. 深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)