浅析JVM内存区域及垃圾回收
一、jvm简介
jvm,全称java virtual machine,即java虚拟机。以java作为编程语言所编写的应用程序都是运行在jvm上的。jvm是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。java有个非常重要的特点就是与平台的无关性,而jvm正是实现这一特点的关键。
jvm对程序的执行主要分为两个步骤,第一步是编译,即将.java的源文件编译成为.class的字节码文件,第二步是解释,jvm对字节码文件进行解释执行。两个步骤流程图分别如下两图所示:
二、jvm内存区域
jvm整个大系统又分为两个子系统。第一个是classloader,即类加载器,功能是将编写的类加载到jvm中。第二个是execution engine,即执行引擎,负责对编译后的字节码文件进行解释执行。上述中execution engine又分为两部分,第一部分是runtime data area,即运行时数据区域,即相当于jvm中的内存,第二部分是native interface,即本地化接口,主要用于执行其他非java编程语言编写的程序。
重点就是前者runtime data area,它分为五个部分,分别是method area(方法区),heap(堆),vm stack(虚拟机栈),program counter register(程序计数器),native method stack(本地方法栈)。前两者线程共享,后三者线程隔离。如下图所示:
概括地说,jvm初始运行的时候都会分配好method area(方法区)和heap(堆),而jvm 每遇到一个线程,就为其分配program counter register(程序计数器)、vm stack(虚拟机栈)、native method stack(本地方法栈), 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为什么把数据区域分为线程共享和线程隔离的原因,线程隔离的那三个区域的生命周期与所属线程相同,而线程共享的区域与java程序运行的生命周期相同,所以这也是系统垃圾回收场所只发生在线程共享的区域(实际上对大部分虚拟机来说是发生在heap上)的原因。关于内存溢出异常如下图所示:
1、method area(方法区)
方法区包括常量池与静态域。存放了所加载类的信息(名称、修饰符等)、类的静态变量、类的常量、类的field信息、类的方法信息。当开发人员在程序中通过class对象中的getname、isinterface等方法来获取信息时,这些数据都来源于方法区。
2、heap(堆)
堆是jvm所管理的内存中最大的一块,几乎所有的对象实例和数组都在此区域,可以认为java中所有通过new创建的对象的内存都在此分配,堆中的对象的内存需要等待gc进行回收。
3、program counter register(程序计数器)
程序计数器是一块较小的内存空间,它是当前线程所执行的字节码的行号指示器,字节码解释器工作时通过改变该计数器的值来选择下一条需要执行的字节码指令,分支、跳转、循环等基础功能都要依赖它来实现。
4、vm stack(虚拟机栈)
虚拟机栈描述的是java方法执行的内存模型,每个方法在执行时都会创建一个栈帧(stack frame),栈帧用于存储局部变量表(基本数据类型、对象的引用等)、操作数栈、动态链接、方法返回地址和一些额外的附加信息。
5、native method stack(本地方法栈)
该区域与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为使用到的本地操作系统(native)方法服务。
三、jvm垃圾回收
jvm的generationalcollecting(垃圾回收)原理是把对象分为年青代(young)、年老代(tenured)、持久代(perm),对不同生命周期的对象使用不同的算法。
通常jvm内存回收总是指heap(堆)内存回收,确实只有heap(堆)中的内容是动态申请分配的,所以以上对象的年轻代和年老代都是指的jvm的heap(堆)空间,而持久代则是之前提到的method area(方法区),不属于heap(堆)。
1. 年轻代
java应用在分配java对象时,这些对象会被分配到年轻代堆空间中去
这个空间大多是小对象并且会被频繁回收
由于年轻代堆空间的垃圾回收会很频繁,因此其垃圾回收算法会更加重视回收效率
2. 年老代
年轻代堆空间的长期存活对象会转移到(也许是永久性转移)年老代堆空间
这个堆空间通常比年轻代的堆空间大,并且其空间增长速度较缓
由于大部分jvm堆空间都分配给了年老代,因此其垃圾回收算法需要更节省空间,此算法需要能够处理低垃圾密度的堆空间
3. 持久代
存放vm和java类的元数据(metadata),以及interned字符串和类的静态变量
当这三个分代的堆空间比较紧张或者没有足够的空间来为新到的请求分配的时候,垃圾回收机制就会起作用。有两种类型的垃圾回收方式:次收集(minor gc)和全收集(full gc)。当年轻代堆空间满了的时候,会触发次收集将还存活的对象移到年老代堆空间。当年老代堆空间满了的时候,会触发一个覆盖全范围的对象堆的全收集。
至此是关于浅析jvm内存区域及垃圾回收,仅供参考。
如有疏漏错误之处,还请不吝赐教!