java运行时数据区

Java运行时数据区域

  众所周知,Java 虚拟机有自动内存管理机制,如果出现内存泄漏和溢出方面的问题,排查错误就必须要了解虚拟机是怎样使用内存的。
包含:程序计数器(PC)、堆、本地方法栈、虚拟机栈、元空间
  下图是 JDK8 之后的 JVM 内存布局。
image

程序计数器(PC)

  • 内存中一块较小的空间,每个线程都有一个 PC,用于存储线程的下一步执行指令。
  • 线程执行的命令,也都是从 PC 中获取的。
  • 线程间的资源切换,就是获取不同线程的PC中的指令,继续执行的。
  • 执行到 Native 方法,计数器值则为空(Undefined)。

本地方法栈

  本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。

虚拟机栈

  • 一般所聊的栈都是虚拟机栈,每个栈里放着栈帧。
  • 一个方法相当于一个栈帧。方法的调用相当于创建一个栈帧,并进行入栈与出栈操作
  • 栈,遵循先进后出原则。栈中栈帧越多,相当于方法套用的层级越多。
  • 栈帧相当于栈的数据结构,包括 局部变量表、操作栈、动态链接、方法返回地址等信息。
    • 局部变量表,存放方法参数和局部变量的区域。 局部变量没有准备阶段, 必须显式初始化。(类在创建时是有准备阶段的)
    • 操作栈,JVM 的执行引擎是基于操作栈的执行引擎。同样是先进后出的栈,用于在方法执行过程中, 会有各种指令往栈中写入和提取信息。
    • 动态链接,每个栈帧中包含一个在常量池中对当前方法的引用, 目的是支持方法调用过程的动态连接。
    • 方法返回地址
      • 正常情况下,返回调用方法的上层地址
      • 抛异常情况下,抛给异常处理的栈针
      • 异常处理情况下,按照 PC 执行以下个指令(内部方法抛异常,外部方法捕获并处理)

i++ 与 ++i 的区别

 int i= 1;
 1. i= i++;
 解析:先将1放入操作栈,在将 i自增+1,再从操作栈中取出 1,并赋值给 i ,结果 i为1;
 2. i= ++i;
 解析:先将 i自增+1,再将1放入操作栈,再从操作栈中取出 1,并赋值给 i ,结果 i为2;

栈结构图

image

  1. 堆,被所有线程共享,在虚拟机启动时创建。
  2. 做为 GC 的主要工作区,java 堆也叫作 “GC 堆”。
  3. 堆采用分代算法
  4. 从内存回收的角度来看,青年代和老年代;青年代又分为Eden空间、From Survivor空间、To Survivor空间等。从内存分配的角度来看,线程共享的 Java 堆中可能划分出多个线程私有的分配缓冲区。
  5. Eden 空间、From Survivor 空间、To Survivor 空间内存分配为 8:1:1 。
  6. 新生代与老年代空间占比 1:2

堆结构图

image

posted @ 2023-10-13 14:59  之士咖啡  阅读(7)  评论(0编辑  收藏  举报