共计 2216 个字符,预计需要花费 6 分钟才能阅读完成。
Java 运行时数据区
JVM 的运行时数据区次要有办法区,堆,虚拟机栈,程序计数器,本地办法栈这几局部,其中办法区和堆是所有线程共有,虚拟机栈,本地办法栈和程序计数器每个线程都有一个。
1、程序计数器
指的是 一块内存区域,底层是 bcp, 字节码指针,用来寄存以后线程执行字节码的行号。
如果线程正在执行的是一个 Java 办法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地(Native)办法,这个计数器值则应为空(Undefined)。
因为 JVM 多线程是通过线程轮流切换,调配处理器执行工夫的形式实现的。也就是说在任意一个确定的时刻,一个处理器只会执行一个线程的一条指令。因而,为了线程切换的后能复原到正确的执行地位,每条线程都须要有一个 独立 的程序计数器,各条线程之间计数器互不影响,独立存储。所以是线程公有。而如果程序计数器 没有 OOM,因为一旦它 OOM 了,程序就不晓得该执行哪个线程的办法,JVM 就会解体。
在 JVM 中相似这样一个循环:
while(not end) {
取 PC 中的地位,找到对应地位的指令;
执行该指令;
PC ++;
}
2、虚拟机栈
讲述的是 Java 办法执行的线程内存模型:每个办法被执行的时候,Java 虚拟机都会同步创立一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动静连贯、办法进口等信息。每一个办法被调用直至执行结束的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
Java 虚拟机以办法作为最根本的执行单元,“栈帧”(Stack Frame)则是用于反对虚拟机进行办法调用和办法执行背地的数据结构,它也是虚拟机运行时数据区中的虚拟机栈(Virtual Machine Stack)的栈元素。栈帧存储了办法的局部变量表、操作数栈、动静连贯和办法返回地址等信息。每一个办法从调用开始至执行完结的过程,都对应着一个栈帧在虚拟机栈外面从入栈到出栈的过程。
然而有一点须要留神,一个栈帧须要调配多少内存,并不会受到程序运行期变量数据的影响,而仅仅取决于程序源码和具体的虚拟机实现的栈内存布局模式。
相当于 cpu 外面的寄存器,用于寄存办法参数和办法外部定义的局部变量。利用办法的 Code 属性的 max_locals 确定最大容量。局部变量表所需的内存空间是在编译期间确定的,在办法运行期间不会扭转局部变量表的大小。
在 Java 虚拟机标准中,对这部分区域规定了两种异样:1、当一个线程的栈深度大于虚拟机所容许的深度的时候,将会抛出 StackOverflowError 异样;2、如果当创立一个新的线程时无奈申请到足够的内存,则会抛出 OutOfMemeryError 异样。
3、本地办法栈
和虚拟机栈相似,然而区别是虚拟机栈为虚拟机执行 Java 办法(也就是字节码)服务,而本地办法栈则为虚拟机应用到的本地办法服务。
一个 Native Method 就是一个 Java 调用非 Java 代码的接囗。该办法的实现由非 Java 语言实现,为 C 或者 C ++ 实现的,和虚拟机栈相似,只不过用于治理非 Java 办法的。
无奈调优和治理,所以个别不论它,晓得有这么一个货色就行
4、Java 堆
堆(heap)是虚拟机中最大的一块内存区域了,被所有 线程共享 ,在虚拟机启动时创立。它的目标便是寄存 对象实例。
堆是垃圾收集器治理的次要区域,因而 很多时候也被成为‘GC’堆(Garbage Collected Heap)。
从垃圾回收的角度来讲,当初的收集器包含 HotSpot 都采纳分代收集算法,所以堆又能够分为:新生代 (Young) 和老年代(Tenured),再粗疏一点,新生代又可分为 Eden、From Survivor 空间和 To Survivor 空间。
从内存调配的角度来讲,又能够分为若干个线程公有的调配缓冲区(Thread Local Allocation Buffer ,TLAB)。
当堆空间有余切无奈扩大,会抛出 OutOfMemoryError 异样。
5、办法区
它用于存储已被虚拟机加载的类型信息,常量,动态变量,即时编译器编译后的代码缓存等数据。
办法区中有一个重要的概念叫运行时常量池,它用来寄存编译器生成的各种字面量与符号援用,它们将在类加载当前放入办法区的运行时常量池中。JVM 虚拟机标准没有很严格的规定,但个别除了保留 Class 文件中形容的符号援用外,还会把符号援用翻译进去的间接援用也存储在外面。运行时常量池有动态性,并非预置入 Class 文件中常量池的内容能力进入办法区运行时常量池,运行期间也能够将新的常量放入池中,这种个性被开发人员利用得比拟多的便是 String 类的 intern()办法。
JVM 虚拟机标准并没有规定如何实现办法区。在 hotspot 中,1.8 以前,用永恒代来实现的办法区。然而这种计划导致 Java 利用更容易在遇到内存溢出问题,而且极少数办法(String::intern())会因为永恒代的起因导致不同虚拟机下有不同的体现。1.8 当前,改用本地内存中实现的元空间(metaspace)来代替。而常量池放在 JVM 堆中了。
6、间接内存
间接内存:间接内存,归操作系统管,不归 JVM 管。1.4 当前新退出 NIO 类,引入了一种基于通道和缓存区的 IO 形式。它通过 native 函数库操作堆外内存,而后通过一个存储在 Java 堆的 DirectByteBuffer 对象作为这块内存的援用进行操作。这样做次要能够提高效率,防止在 Java 堆和 Native 堆中来回复制数据。