java虚拟机运行时内存区域

java虚拟机运行时内存区域

程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区 (前3个为线程私有,后2个为线程共享)


(1)程序计数器

当前线程所执行的字节码的行号指示器;通过改变这个计数器的值来选取下一条需要执行的字节码指令;分支、循环、跳转、异常处理、线程恢复等功能依赖其完成;线程切换后能恢复到正确的执行位置,故每个线程需要一个独立的程序计数器,即“线程私有“

(2)Java虚拟机栈

  • Java Virtual Machine Stacks; 也就是通常所说的“栈”;线程私有;
  • 存在数据结构–栈帧(Stack Frame),用于存储局部变量表、操作数栈、方法出口等;局部变量表中存放了编译期可知的基本数据类型(boolean,int…)、对象引用(reference,可以理解为指向对象起始位置的引用指针,或者代表对象的句柄)
  • 存在两种异常: 1)StackOverflowError(栈溢出): 请求栈深度大于虚拟机栈深度 2)OutOfMemoryError(OOM): 动态扩展内存时,无法申请到足够的内存

(3)本地方法栈

与虚拟机栈作用类似;虚拟机栈为虚拟机执行Java方法服务,本地方法栈为虚拟机使用到底Native方法服务; 也会抛出StackOverflowError和OutOfMemoryError异常

(4)Java堆

  • Java Heap;所有线程共享的一块内存区域;唯一目的:存放对象实例(对象实例和数组);
  • java堆是垃圾收集器管理的主要区域;一般采用分代收集算法;细分为:新生代和老年代,再细致点有Eden空间、From Survivor空间、To Survivor空间等;某些情况下,Java堆坑可能划分出多个线程私有的分配缓冲区(TLAB);
  • 可以通过-Xmx和-Xms控制堆大小;当堆内存无法扩展时,会抛出OOM

(5)方法区

  • 线程共享的内存区域;用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;在HotSpot虚拟机中称为“永久代”
  • __运行时常量池__是方法区的一部分, 用于存放编译器生成的各种字面量和符号引用;运行时也可能将新的常量放入池中,例如String的intern()方法
  • jdk8取消了永久代,存储在永久代的部分数据就已经转移到Java Heap或者Native memory,符号引用(Symbols)转移到了native memory;字符串常量池(interned strings)转移到了Java heap;类的静态变量(class statics)转移到了Java heap;方法存放于元空间(Metaspace)

注:直接内存(Direct Memory):不是虚拟机中的内存区域;NIO中基于通道(Channel)和缓冲区(Buffer)的IO方式,可以使用Native函数库分配对外内存,然后通过DirectByteBuffer作为引用对其操作,不会收到堆大小的限制。

猜你喜欢

转载自blog.csdn.net/l947069962/article/details/84326847