JVM内存

最后一次更新时间:Tuesday, July 28th 2020, PM

 

Java内存(运行时数据区)
 
在Java1.8之前长这样:

在Java1.8之后长这样:

二者最大的区别即图中蓝框所示的部分。在Java1.8之后,“方法区”改名为“元空间”,且放入直接内存(系统内存)中,不再属于JVM内存,相关介绍在本文方法区部分有讲。大部分面试是以Java1.8之前的版本来进行考量

 

接下来我们分别来介绍JVM内存组成部分。

Java虚拟机栈(VM Stack)

虚拟机栈是为Java字节码相关功能服务的。(我的理解是服务于Java代码相关部分)。

虚拟机栈结构包括

  • 局部变量表
  • 操作数栈
  • 动态链接
  • 方法出口

其中,局部变量表 负责存放各种数据类型(int,byte,char … )以及对象的引用(reference类型)

虚拟机栈的生命周期由其线程生命周期决定(很好理解,虚拟机栈就是属于某个线程)。

虚拟机栈的两种异常:
1.StackOverFlowError:Stack不支持动态拓展,Stack 用完了
2.OutOfMemoryError :Stack 支持动态拓展,Memory用完了

本地方法栈

本地方法栈只为Native方法服务(Native方法:非Java代码实现的方法)。

本地方法栈的结构生命周期异常与虚拟机栈类似,此处不赘述。

 

 

 

堆(Heap)

堆是JVM中最大的一块内存,只存放 对象实例 以及 数组。

是垃圾收集器管理的主要区域,因此也被称为“GC堆”

从垃圾回收的角度看,堆可以划分为 新生代 和 老年代(至于我们常说的 永久代 并不属于堆内存)。新生代可继续划分为Eden区和Survivor区。Survivor区可继续划分为S0区和S1区。相关内容我会在Java垃圾回收篇详说,此处留白。

 

 

 

方法区

方法区用来存储 类信息、常量、静态变量、编译后的代码 等数据。

实现方法区的内存也被称为 永久代(PermGen)

Java1.8之后,方法区变为元空间(MetaSpace),使用直接内存。这样做的好处是:
不受JVM内存限制,不会触发OutOfMemoryError

 

 

 

常量池 (方法区的一部分)

常量池的结构如下:

  • 字面量
    • 文本字符串
    • final修饰的常量
    • 基本数据类型的值
    • 其它
  • 符号引用
    • 类和结构的完全限定名
    • 字段名称 和 描述符
    • 方法名称 和 描述符

除特别声明外,本站所有文章均采用 CC BY-SA 4.0 协议 ,转载请注明出处!