Java运行时数据区域

JDK8 之后的 JVM 内存布局

程序计数器(PC)

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

栈(虚拟机栈、本地栈)

虚拟机栈

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

在这里插入图片描述

本地方法栈

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

在这里插入图片描述

Java堆

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

方法区

  1. 被所有线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
  2. 方法区,在JDK 1.8 以前在Java堆中。JDK 1.8 及以后在 本地内存中
  3. JDK8 之前,Hotspot 中方法区的实现是永久代(Perm),JDK8开始使用元空间(Metaspace),以前永久代所有内容的字符串常量移至堆内存,其他内容移至元空间,元空间直接在本地内存分配。

Java 8 中 PermGen 为什么被移出 HotSpot JVM 了?

  • 由于 PermGen 内存经常会溢出,引发恼人的 java.lang.OutOfMemoryError,因此,移出 避免OOM 的出现。
  • 移除 PermGen 可以促进 HotSpot JVM 与JRockit VM 的融合,因为 JRockit 没有永久代。
  • 结果:PermGen 最终被移除,方法区移至Metaspace,字符串常量移至 Java Heap。

JDK8 之前的内存区域图如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值