JVM运行时数据区域

JVM运行时数据区域
文章图片
运行时数据区.png
图中白色为线程独有,图中蓝色为线程之间共有
1. 线程计数器
当前线程执行字节码的行号指示器。
字节码解释器就是通过改变这个值来指示下一条需要执行的字节码指令。循环、跳转等基础功能都是依赖这个来实现。
当线程正在执行一个Java方法,线程计数器指向的是正在执行的字节码的地址。当线程正在执行一个Native方法时,则线程计数器为空。因为Native方法不存在字节码的概念。
特点:线程独有。 原因:在多线程程序中,由于CPU个数的限制,需要线程的切换,为了能够在线程切换后回到原来的执行位置,就需要线程计数器。
2. 虚拟机栈
虚拟机栈:描述的是Java方法执行的内存模型。
每个方法在执行的时候同时都会创建一个栈帧--用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法在开始被调用直至执行结束,就对应着一个栈帧在虚拟机栈中入栈和出栈的过程。
局部变量表

  • 存储的是编译期可知的基本数据类型、对象引用(referance)和returnAddress类型(这个东西具体是什么,后续再讲)。
  • 除了long和double占两个局部变量空间(Slot)。其他都占一个Slot,所以局部变量表在编译期就可以确定内存空间大小,在运行期间不会再变。
可抛两种异常:线程请求的栈深度大于虚拟机允许的深度抛出StackOverFlow异常;在虚拟机是可扩展的基础上(并不是无限,也有一个固定长度),当请求无法申请足够的内存时,抛出OutOfMemoryError异常。
3. 本地方法栈
  • 本地方法栈(Native Method Stack)与虚拟机栈作用非常相似。区别是虚拟机栈为执行Java方法服务,本地方法栈为执行Native方法服务。而有点虚拟机版本(HotSpot)直接把两者合二为一。
  • 与虚拟机栈一样可抛出StackOverFlow和OutOfMemoryError异常。
4. 堆
  • JVM管理的内存中最大的一块。线程间共享。JVM启动时创建。
  • 唯一目的就是存放对象实例。即堆中只可能存放对象实例。
  • Java虚拟机规范的规定:堆可以是物理上不连续的内存空间,只要是逻辑上连续就可以了。可以固定大小,也可以可扩展。
  • 可以通过-Xmx和-Xms来控制扩展大小。
  • 当不够用时,会抛出OutOfMemoryError异常。
5. 方法区
  • 线程间共享
  • 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等信息。
  • Java虚拟机规范对此内存的要求非常宽松。物理上可以不连续,甚至可以不实现垃圾回收。
  • 垃圾回收在此上的成绩并不理想,主要是:类的卸载和常量池的回收。
  • 当不够用时,会抛出OutOfMemoryError异常。
6. 运行时常量池
是方法区的一部分。
  • 在Class文件中会有一部分数据用来记录常量信息,被称为Constant Pool Table(后续会讲到)。它用于存放编译期生成的字面量和符号引用。在类加载后,这部分信息就被放入运行时常量池中。
  • 但要注意的是,运行时常量池中并不全是Constant Pool Table放进来的,因为运行期间可以把常量放入运行时常量池中,比如String类的intern方法。这种现象使之具有动态性。
  • 当不够用时,会抛出OutOfMemoryError异常。
7. 直接内存
  • 并不属于JVM内存管理中的一部分,但在Java程序里也会被用到。
  • JDK1.4新加入了NIO(New I/O),引入了基本管道和缓冲区的IO方式,它使用Native方法直接分配堆外内存。
  • 它不受堆大小限制,但受机器的总内存限制,也有可能出现OutOfMemoryError异常。
【JVM运行时数据区域】另加
博主个人感悟:做笔记是对的,切记不要照抄书本上的东西。
一定加入自己的理解在里面。不然就会过目就忘,也达不到深层的理解。

    推荐阅读