JVM-01内存

329 阅读3分钟

4.png

程序计数器

线程独享,代表当前执行字节码文件的行号,通过改变程序计数器的值来获取下一条指令 不存在内存溢出。

  • 执行java方法时,指向字节码行号
  • 执行native方法时,指向Undefined 唯一没有规定out of memory Error 的内存区域

虚拟机栈

  • 线程私有,描述的是Java方法执行的线程内存模型,即线程运行时所需的内存空间。
  • 每个方法被执行时,虚拟机都会创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法出口等信息。
  • 栈由栈帧组成,每个栈帧对应一个方法调用时所需的内存空间
  • 只能有一个活动栈帧,对应正在执行的方法。

方法的调用到执行完毕对应着栈帧的入栈和出栈 一般我们指的栈是对应着虚拟机栈中的局部变量表,不同数据类型在局部变量表中的空间大小用变量槽表示(一个变量槽可以是64bit也可以是32bit),Long和Double占2个变量槽,其余均占1个变量槽。

局部变量表所需的内存空间在编译期间完成分配,在方法运行期间不会改变局部变量表的大小。这里说的“大小”是指变量槽的数量

本地方法栈

虚拟机栈为虚拟机执行Java方法(也就是字节码)服务, 而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。

内存中最大的一块,所有线程共享,存放对象实例。 堆的物理位置可以不连续但逻辑位置必须连续。

字符串常量池是放在堆中的。

方法区

用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

在《java虚拟机规范》中被视为堆的逻辑部分,但也有另一个别名“非堆”。 在JDK1.8之前用永久代来实习方法区,但方法区并不等同于永久代。 如今 已经将方法区移到了直接内存中。

运行时常量池

方法区的一部分。

Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

运行时常量池还具有动态性

Java语言并不要求常量一定只有编译期才能产生,也就是说,并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可以将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的 intern()方法。

直接内存

在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区 (Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作

直接内存不受堆大小限制,但受总内存大小限制。在设置虚拟机参数时需额外注意。