JVM内存结构

JDK、JVM、Jre之间的关系

JVM的三大区域

注意: JVM是边解释边执行的

运行时数据区

定义:Jre在执行Java程序的过程中会把他所管理的内存划分成若干个不同的数据区域。包括: - 程序计数器 - 虚拟机栈 - 本地方法栈 用来保存native方法的信息 - Java堆 - 方法区(运行时常量池) - 直接内存(也叫堆外内存,用于nio)

线程私有

线程共享

程序计数器

程序计数器是一个很小的内存区域,指向当前线程正在执行的指令对应的字节码地址(指针)

为什么需要程序计数器?

CPU时间片轮转回来的时候,通过程序计数器才直到程序执行到了哪里,以及从哪继续执行。

JVM的内存区域中,程序计数器是唯一不会OOM的储存区

虚拟机栈

栈:FILA,后进先出。

虚拟机栈用来存储当前线程运行方法所需的数据、指令、返回地址等。

栈帧

1
2
3
private void test(){
    int i = 0;
}

当以上函数进入虚拟机栈时,就成为了一个栈帧,他内部做了两件事:

  1. 首先函数中有个创建变量i的操作,入栈到操作数栈;
  2. 将操作数栈的栈顶操作生成的数据(i)存入局部变量表下标为[1]的位置(局部变量表下标[0]位置是this,代表实例自己)。

Java的解释执行是基于操作数栈,所以移植性和兼容性好,而C语言是基于寄存器(硬件)运算,所以速度快。

虚拟机栈的大小 -Xss

本地方法栈

用来保存native方法的信息。比如hashCode()方法等加了native关键字的方法。

本地方法栈中存放的其实是C函数的链接,由于不是java方法,所以程序计数器不会计数。

方法区

用来存放:

Java堆

用来存放:

参数:

问题,为何要分成方法区和堆

堆位于新生代和老年代,回收频繁;而方法区位于永生代(1.8叫元空间,使用的是物理内存,提升了容量),回收不频繁。这是一种动静分离的思想,有利于回收的高效。

怎么可视化查看内存

内存溢出

常见的内存溢出有以下三种:

遗留问题

1.JVM 有哪些内存区域?(JVM 的内存布局是什么?) 2.StackOverFlow与OOM的区别?分别发生在什么时候,JVM栈中存储的是什么?堆中存储是什么?

今天状态不好,学的云里雾里,时间不够快下班了,也懒得总结了,留到后面再说吧。