概述:
JAVA虚拟机在执行Java程序的过程会把它管理的内存划分为不同的数据区,这些运行时的内存区有的随JAVA虚拟机进程的启动而存在,有的内存区随着用户线程的启动而建立,同样伴随着线程的结束而销毁。
(注:本文后续不断更新中)
本文作者:Horace_hr
作者博客地址:https://blog.csdn.net/Horace_hr
本文地址:https://blog.csdn.net/Horace_hr/article/details/94971918(转载请标明出处,谢谢!)
JAVA运行时的数据区域一般分为以下几块:
1、堆内存
2、方法区
3、JVM虚拟机栈
4、本地方法栈
5、程序计数器
一、程序计数器(Program Counter Register)
程序计数器在JVM中占据很小的一块内存,其作用在于记录线程在执行的字节码的当前行数和位置,可以称之为行号指示器。在多线程环境中CPU会交替式切换着执行多个线程的指令,但在同一时刻只能执行一个线程的命令,为了线程切换后能恢复到之前的执行的位置,需要为每个线程单独引入程序计数器,各线程之前互不干扰,独立存储。
程序计数器有什么作用呢?从以上释义中归纳出两点:
- 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,比如:顺序执行/选择/循环/异常处理。
- 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行的位置并继续运行。
程序计数器的特点如下:
- 线程私有,不能共享;
- 线程执行JAVA方法时,程序计数器记录的是当前执行的JVM字节码指令的位置;线程执行NATIVE方法时,程序计数器的值为undefined;
- 是唯一一块不会出现OutOfMemory异常的内存区域。因为Java程序计数器记录指令的偏移地址,这个地址的值其范围是可知的,在程序计数器建立之初就能分配一个绝对不会溢出的内存。
二、JAVA 虚拟机栈(Java Virtual Machine Stacks)
JAVA虚拟机栈也是线程私有的,它随着线程的开始而存在,线程的结束而销毁。每个Java方法在执行的过程中都会在JAVA 虚拟机栈中创建一个栈帧用来存放Java方法的局部变量表、操作数栈、动态链接、方法出口等信息。其中局部变量表最常用,它记录的是编译期间的基本数据类型(byte,int,short等等)、对象引用类型(类、数组、接口等的引用地址)等。局部变量表的内存在编译期间就已经完成分配,其内存大小是确定好的,在运行期间不会变化。因为在线程进入一个方法进行内存分配的时候,可能会遇到两种异常:
- Stackoverflow: 此为线程请求的栈深度超过了规定的JVM允许的深度造成的
- OutOfMemory:此为JVM栈在动态拓展时无法申请到足够的内存造成的
三、本地方法栈(Native Method Stocks)
本地方法栈和JAVA虚拟机栈的发挥的作用很类似,同样是线程私有的。只是JAVA虚拟机栈作用的对象是Java方法,本非方法栈作用的对象是本地方法。因为类似故不做赘述
四、JAVA堆(Java Heap)
JAVA堆是JAVA虚拟机所管理的内存中最大的一块,所有线程可共享,在JVM启动时创建。此内存的作用就是用来存放对象实例,大部分对象实例都在此分配内存。JAVA堆是垃圾回收管理器重点管理的区域。
五、方法区(Method Area)
方法区是线程共享的,用于存储JVM加载的类信息、常量、静态变量等。运行时常量池就属于方法区的一部分。垃圾回收机制对方法区的回收主要是对对常量池的回收和对类型的卸载。一般而言,方法区的垃圾回收效果并不是十分好,尤其是类型的卸载比较困难,但还是有必要对方法区进行垃圾回收的。
(注意方法区不等同于堆)
(注:本文后续不断更新中)
引用
本文参考资料为周志明编著《深入理解JAVA虚拟机》
请各位小伙伴不吝赐教,多多批评。喜欢的小伙伴可以“推荐”一下,不胜感谢!