虚拟机的结构
类加载子系统
类加载子系统负责从文件系统或者网络中加载Class 信息,加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中可能还会存放运行时常量池信息,包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)。
Java堆:
在虚拟机启动的时候建立,它是Java程序最主要的内存工作区域。几乎所有的Java对象实例都存放于Java堆中。堆空间是所有线程共享的,这是一块与Java应用密切相关的内存区间。
直接内存
Java的NIO库允许Java程序使用直接内存。直接内存是在Java堆外的、直接向系统申请的内存区间。通常,访问直接内存的速度会优于Java堆。因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。由于直接内存在Java堆外,因此它的大小不会直接受限于Xmx指定的最大堆大小,但是系统内存是有限的,Java 堆和直接内存的总和依然受限于操作系统能给出的最大内存。
垃圾回收系统
是Java虛拟机的重要组成部分,垃圾回收器可以对方法区、Java堆和直接内存进行回收。其中,Java 堆是垃圾收集器的工作重点。
java栈 (虚拟机栈 线程栈)
每一个Java虚拟机线程都有一个私有的 Java栈。一个线程的Java栈在线程创建的时候被创建。Java 栈中保存着帧信息,Java 栈中保存着局部变量、方法参数,同时和Java方法的调用、返回密切相关。
本地方法栈和Java栈非常类似,最大的不同在于Java栈用于Java方法的调用,而本地方
法栈则用于本地方法调用。作为对Java虛拟机的重要扩展,Java虚拟机允许Java直接调用本地方法(通常使用C编写)。
PC ( Program Counter)寄存器 程序计数器
PC ( Program Counter)寄存器也是每个线程私有的空间,Java 虚拟机会为每一个 Java线程
创建PC寄存器。在任意时刻,一个Java 线程总是在执行一个方法,这个正在被执行的方法称当前方法。
执行引擎
执行引擎是Java虚拟机的最核心组件之一, 它负责执行虚拟机的字节码。现代虚拟机为了提高执行效率,会使用即时编译技术将方法编译成机器码后再执行。
方法区
JDK1.7被称之为永久区 1.8之后消失变成元空间(Meta space)来进行存储我们的类
代替方法区的Meta space是分配到直接内存当中的
简述JVM内存模型
线程私有的运行时数据区:程序计数器,Java虚拟机栈,本地方法栈。
线程共享的运行时数据区:Java堆,方法区。
简述程序计数器
程序计数器表示当前线程所执行的字节码的行号指示器。
程序计数器不会产生StackOverflowError和OutOfMemoryError。
简述虚拟机栈
Java虚拟机栈用来描述Java方法执行的内存模型,线程创建时就会分配一个栈空间,线程结束后栈空间被回收。
栈中元素用于支持虚拟机进行方法调用,每个方法在执行时都会创建一个栈帧存储方法的局部变量表、操作栈、动态链接和返回地址等消息。
虚拟机栈会产生两类异常:
StackOverflowError:线程请求的栈深度大于虚拟机允许的深度抛出。
OutOfMemoryError:如果 JVM 栈容量可以动态扩展,虚拟机栈占用内存超出抛出。
简述本地方法栈
本地方法栈与虚拟机栈作用相似,不同的是虚拟机栈为虚拟机执行Java方法服务,本地方法栈为本地方法服务。可以将虚拟机栈看作普通的java函数对应的内存模型,本地方法栈看作由native关键词修饰的函数对应的内存模型。
本地方法栈会产生两类异常:
StackOverflowError:线程请求的栈深度大于虚拟机允许的深度抛出。
OutOfMemoryError:如果JVM栈容量可以动态扩展,虚拟机栈占用内存超出抛出。
简述JVM中的堆
堆主要作用是存放对象实例,Java里几乎所有对象实例都在堆上分配内存,堆也是内存管理中最大的一块。Java的垃圾回收主要就是针对堆这一区域进行。可通过-Xms和-Xmx设置堆的最小和最大容量。
堆会抛出OutOfMemoryError异常。
简述方法区
方法区用于存储被虚拟机加载的类信息、常量、静态变量等数据。
JDK6之前使用永久代实现方法区,容易内存溢出。JDK7把放在永久代的字符串常量池、静态变量等移出,JDK8中抛弃永久代、改用在本地内存中实现的元空间来实现方法区,把JDK7中永久代内容移到元空间。
方法区会抛出OutOfMemoryError异常。
简述运行时常量池
运行时常量池存放常量池表,用于存放编译器生成的各种字面量与符号引用。一般除了保存Class文件中描述的符号引用外,还会把符号引用翻译的直接引用也存储在运行时常量池。除此之外,也会存放字符串基本类型。
JDK8之前放在方法区,大小受限于方法区。JDK8将运行时常量池存放在堆中。
简述直接内存
直接内存也称为对外内存,就是把内存对象分配在JVM堆外的内存区域。这部分内存不是虚拟机管理,而是由操作系统来管理。Java通过DriectByteBuffer对其进行操作,避免了在java和Native堆来回复制数据。
以上就是这一篇文章的全部内容,请大家期待下一篇文章。