JVM 控制的内存区域

主要分为 3 块:

  • 线程私有区域(程序计数器、虚拟机栈、本地方法栈)

  • 线程共享区域(堆、方法区)

  • 直接内存(不是 JVM 运行时数据区域的一部分。如 JDK 中的 nio 使用本地函数库分配堆外内存,使用缓冲区进行这块内存的读写


3  块内存区域的生命周期:

  • 线程私有区域,随着用户线程的启动而创建,线程的结束而销毁。

  • 线程共享区域,随着虚拟机的启动而创建,虚拟机的停止而销毁。

  • 直接内存,通过本地函数库 Unsafe 分配与释放内存。


图片



线程私有区域


1、程序计数器(Program Counter Register)

  • 一块较小的内存空间, 是当前线程所执行的字节码的行号指示器

  • 每条线程都要有一个独立的程序计数器

  • 执行 Java 方法时,程序计数器记录的是字节码指令的地址;执行本地方法时,为空

  • 唯一一个没有内存溢出区域


2、虚拟机栈(VM Stack)

  • 描述 java 方法执行的内存模型

  • 每个方法在执行的同时都会创建一个栈帧(Stack Frame) 用于存储局部变量表、操作数栈、动态链接、方法出口等信息

  • 每一个方法从调用直至执行完成的过程,对应着一个栈帧在虚拟机栈中入栈到出栈的过程

  • 栈帧是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁。方法正常完成、抛出异常未捕获都算作方法结束。


3、本地方法栈(Native Method Stack)

  • 虚拟机栈为执行 Java 方法服务;本地方法栈为 Native 方法服务

  • 本地方法栈深度溢出或者栈扩展失败时,也会分别抛出 StackOverflowError 和 OutOfMemoryError异常



线程共享区域


1、堆(Heap)

  • 垃圾收集最重要的内存区域

  • 虚拟机规范规定,创建的对象和数组都应当保存在堆内存中

  • 一般大小可扩展,通过 -Xms 和 -Xmx 设定最小值和最大值,无法扩展时抛出 OutOfMemoryError 异常


2、方法区(Method Area)

  • 存储被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

  • 运行时常量池(Runtime Constant Pool)是方法区的一部分,生成的各种字面量与符号引用也在其中



图片



至此可以回答类的静态变量存放在 JVM 运行时的哪块内存了。

HotSpot VM,JDK 6 及之前版本静态变量存放在永久代(Permanent Generation,使用永久代实现的方法区)中;JDK 7 开始,静态变量改存放到 java.lang.Class 对象的末尾,即 Heap 中。虚拟机规范中,是把方法区描述为堆的一个逻辑部分,以上的差异只是实现细节不同。


更多相关文章

  1. 多线程基础必要知识点!看了学习多线程事半功倍
  2. 模板方法模式在开源代码中应用
  3. 多线程三分钟就可以入个门了!
  4. 构造方法的参数太多,如何解决?
  5. 记一次应用线程被阻塞的问题排查
  6. 异步获取线程计算的结果-Future
  7. Redis为什么又引入了多线程?作者也逃不过“真香定理”?
  8. 详解第三种创建线程的方式-Callable接口
  9. java线程相关面试题(第一版)

随机推荐

  1. 2.docker容器管理、仓库管理、数据管理、
  2. CopyOnWriteArrayList你都不知道,怎么拿of
  3. 从零单排学Redis【铂金一】
  4. 龙归科技 | 对未来的若干猜测
  5. 1.docker介绍安装,镜像管理,通过容器、模板
  6. 从零单排学Redis【铂金二】
  7. 华为帐号服务升级,助力应用快速验证用户身
  8. 100道Java并发和多线程基础面试题大集合(
  9. Real World CTF 2020 DBaaSadge Writeup
  10. 外行人都能看得懂的机器学习,错过了血亏!