初识JVM内存区域的划分

初识JVM内存区域的划分

初识JVM内存区域的划分

我们知道,当Java源代码(.java)文件被编译后,会变成字节码(.class)文件,它是一个二进制文件。然后字节码文件就会被加载进Java虚拟机中(即:JVM中)。而JVM中又是怎样的呢?

初识JVM内存区域的划分被分为了如下的几个区域:
如下图:
在这里插入图片描述

  • 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址.
  • 虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] arr 这样的存储地址的引用就是在这里保存.
  • 本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.
  • 堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} )
  • 方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域.
  • 运行时常量池(Runtime Constant Pool): 是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从 JDK 1.7 开始, 运行时常量池在堆上).

Native 方法:
JVM 是一个基于 C++ 实现的程序. 在 Java 程序执行过程中, 本质上也需要调用 C++ 提供的一些函数进行和操作系统底层进行一些交互. 因此在 Java 开发中也会调用到一些 C++ 实现的函数.
这里的 Native 方法就是指这些 C++ 实现的, 再由 Java 来调用的函数.

每一个线程都有自己的程序计数器和JVM Stack以及本地方法栈。而堆和方法区是所有线程共享的。

  • 局部变量和引用保存在栈上, new 出的对象保存在堆上.
  • 堆的空间非常大, 栈的空间比较小.
  • 堆是整个 JVM 共享一个, 而栈每个线程具有一份(一个 Java 程序中可能存在多个栈).

总结:

  1. 引用和对象都是一种数据组织形式,所以都是存放在内存中的。
  2. 对象一定保存在堆上。但引用则不一定。
  3. 引用是一类只能用来指向对象的数据类型。
  4. 引用可以指向对象,也可以不指向对象。
  5. 解引用操作就是通过引用找到对象。
  6. java 中我们无法直接接触到对象,都是通过引用接触到对象。
  7. 对一个空的引用做解引用操作,会出现 NullPointerException
  8. JVM 为了便于管理,讲它管理的内存人为的划分成 6 个区域:
  1. PC 区
  2. 虚拟机栈
  3. 本地方法栈
  4. 方法区
  5. 运行时常量池

猜你喜欢

转载自blog.csdn.net/weixin_52142731/article/details/112055335