jvm内存回收机制

Java垃圾回收概况

  Java GC(Garbage Collection,垃圾搜集,垃圾回收)机制,是Java与C++/C的主要区分之1,作为Java开发者,1般不需要专门编写内存回收和垃圾清算代 码,对内存泄漏和溢出的问题,也不需要像C程序员那样战战兢兢。这是由于在Java虚拟机中,存在自动内存管理和垃圾打扫机制。概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并肯定哪些内存需要回收,根据1定的回收策略,自动的回收内存,永不停息(Nerver
Stop)的保证JVM中的内存空间,放置出现内存泄漏和溢出问题。

  关于JVM,需要说明1下的是,目前使用最多的Sun公司的JDK中,自从 1999年的JDK1.2开始直至现在仍在广泛使用的JDK6,其中默许的虚拟机都是HotSpot。2009年,Oracle收购Sun,加上之前收购 的EBA公司,Oracle具有3大虚拟机中的两个:JRockit和HotSpot,Oracle也表明了想要整合两大虚拟机的意图,但是目前在新发布
的JDK7中,默许的虚拟机依然是HotSpot,因此本文中默许介绍的虚拟机都是HotSpot,相干机制也主要是指HotSpot的GC机制。

  Java GC机制主要完成3件事:肯定哪些内存需要回收,肯定甚么时候需要履行GC,如何履行GC。经过这么长时间的发展(事实上,在Java语言出现之前,就有 GC机制的存在,如Lisp语言),Java GC机制已日臻完善,几近可以自动的为我们做绝大多数的事情。但是,如果我们从事较大型的利用软件开发,曾出现过内存优化的需求,就一定要研究 Java GC机制。

  学习Java GC机制,可以帮助我们在平常工作中排查各种内存溢出或泄漏问题,解决性能瓶颈,到达更高的并发量,写出更高效的程序。

JAVA内存划分

了解Java GC机制,必须先清楚在JVM中内存区域的划分。在Java运行时的数据区里,由JVM管理的内存区域分为下图几个模块:

其中:

1,程序计数器(Program Counter Register):程序计数器是1个比较小的内存区域,用于唆使当前线程所履行的字节码履行到了第几行,可以理解为是当前线程的行号唆使器。字节码解释器在工作时,会通过改变这个计数器的值来取下1条语句指令。

  每一个程序计数器只用来记录1个线程的行号,所以它是线程私有(1个线程就有1个程序计数器)的。

  如果程序履行的是1个Java方法,则计数器记录的是正在履行的虚拟机字节码指令地址;如果正在履行的是1个本地(native,由C语言编写 完成)方法,则计数器的值为Undefined,由于程序计数器只是记录当前指令地址,所以不存在内存溢出的情况,因此,程序计数器也是所有JVM内存区 域中唯逐一个没有定义OutOfMemoryError的区域。

2,虚拟机栈(JVM Stack)1个线程的每一个方法在履行的同时,都会创建1个栈帧(Statck Frame),栈帧中存储的有局部变量表、操作站、动态链接、方法出口等,当方法被调用时,栈帧在JVM栈中入栈,当方法履行完成时,栈帧出栈。

  局部变量表中存储着方法的相干局部变量,包括各种基本数据类型,对象的援用,返回地址等。在局部变量表中,只有long和double类型会占 用2个局部变量空间(Slot,对32位机器,1个Slot就是32个bit),其它都是1个Slot。需要注意的是,局部变量表是在编译时就已肯定 好的,方法运行所需要分配的空间在栈帧中是完全肯定的,在方法的生命周期内都不会改变。

  虚拟机栈中定义了两种异常,如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StatckOverFlowError(栈溢出);不过量 数Java虚拟机都允许动态扩大虚拟机栈的大小(有少部份是固定长度的),所以线程可以1直申请栈,知道内存不足,此时,会抛出 OutOfMemoryError(内存溢出)。

  每一个线程对应着1个虚拟机栈,因此虚拟机栈也是线程私有的。

3,本地方法栈(Native Method Statck)本地方法栈在作用,运行机制,异常类型等方面都与虚拟机栈相同,唯1的区分是:虚拟机栈是履行Java方法的,而本地方法栈是用来履行native方法的,在很多虚拟机中(如Sun的JDK默许的HotSpot虚拟机),会将本地方法栈与虚拟机栈放在1起使用。

  本地方法栈也是线程私有的。

4,堆区(Heap)堆区是理解Java GC机制最重要的区域,没有之1。在JVM所管理的内存中,堆区是最大的1块,堆区也是Java GC机制所管理的主要内存区域,堆区由所有线程同享,在虚拟机启动时创建。堆区的存在是为了存储对象实例,原则上讲,所有的对象都在堆区上分配内存(不过现代技术里,也不是这么绝对的,也有栈上直接分配的)。

  1般的,根据Java虚拟机规范规定,堆内存需要在逻辑上是连续的(在物理上不需要),在实现时,可以是固定大小的,也能够是可扩大的,目前主 流的虚拟机都是可扩大的。如果在履行垃圾回收以后,仍没有足够的内存分配,也不能再扩大,将会抛出OutOfMemoryError:Java heap space异常。

  关于堆区的内容还有很多,将在下节“Java内存分配机制”中详细介绍。

5,方法区(Method Area)在Java虚拟机规范中,将方法区作为堆的1个逻辑部份来对待,但事实 上,方法区其实不是堆(Non-Heap);方法区是各个线程同享的区域,用于存储已被虚拟机加载的类信息(即加载类时需要加载的信息,包括版本、field、方法、接口等信息)、final常量、静态变量、编译器即时编译的代码等。

  方法区在物理上也不需要是连续的,可以选择固定大小或可扩大大小,并且方法区比堆还多了1个限制:可以选择是不是履行垃圾搜集。1般的,方法区上 履行的垃圾搜集是很少的,这也是方法区被称为永久代的缘由之1(HotSpot),但这也不代表着在方法区上完全没有垃圾搜集,其上的垃圾搜集主要是针对 常量池的内存回收和对已加载类的卸载。

  在方法区上进行垃圾搜集,条件刻薄而且相当困难,效果也不使人满意,所以1般不做太多斟酌,可以留作以落后1步深入研究时使用。

  在方法区上定义了OutOfMemoryError:PermGen space异常,在内存不足时抛出。

  运行经常量池(Runtime Constant Pool)是方法区的1部份,用于存储编译期就生成的字面常量、符号援用、翻译出来的直接援用符号援用就是编码是用字符串表示某个变量、接口的位置,直接援用就是根据符号援用翻译出来的地址,将在类链接阶段完成翻译;运行经常量池除存储编译期常量外,也能够存储在运行时间产生的常量(比如String类的intern()方法,作用是String保护了1个常量池,如果调用的字符“abc”已在常量池中,则返回池中的字符串地址,否则,新建1个常量加入池中,并返回地址)。

6,直接内存(Direct Memory)直接内存其实不是JVM管理的内存,可以这样理解,直接内存,就是 JVM之外的机器内存,比如,你有4G的内存,JVM占用了1G,则其余的3G就是直接内存,JDK中有1种基于通道(Channel)和缓冲区 (Buffer)的内存分配方式,将由C语言实现的native函数库分配在直接内存中,用存储在JVM堆中的DirectByteBuffer来援用。
由于直接内存收到本机器内存的限制,所以也可能出现OutOfMemoryError的异常。

Java内存分配机制

这里所说的内存分配,主要指的是在堆上的分配,1般的,对象的内存分配都是在堆上进行,但现代技术也支持将对象拆成标量类型(标量类型即原子类型,表示单个值,可以是基本类型或String等),然后在栈上分配,在栈上分配的很少见,我们这里不斟酌。

  Java内存分配和回收的机制概括的说,就是:分代分配,分代回收。对象将根据存活的时间被分为:年轻代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation,也就是方法区)。以下图(来源于《成为JavaGC专家part I》,http://www.importnew.com/1993.html):

    

  年轻代(Young Generation):对象被创建时,内存的分配首先产生在年轻代(大对象可以直接 被创建在年老代),大部份的对象在创建后很快就不再使用,因此很快变得不可达,因而被年轻代的GC机制清算掉(IBM的研究表明,98%的对象都是很快消 亡的),这个GC机制被称为Minor GC或叫Young
GC。注意,Minor GC其实不代表年轻代内存不足,它事实上只表示在Eden区上的GC。

  年轻代上的内存分配是这样的,年轻代可以分为3个区域:Eden区(伊甸园,亚当和夏娃偷吃禁果生娃娃的地方,用来表示内存首次分配的区域,再 贴切不过)和两个存活区(Survivor 0 、Survivor 1)。内存分配进程为(来源于《成为JavaGC专家part I》,http://www.importnew.com/1993.html):

    

波比源码 – 精品源码模版分享 | www.bobi11.com
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

波比源码 » jvm内存回收机制

发表评论

Hi, 如果你对这款模板有疑问,可以跟我联系哦!

联系站长
赞助VIP 享更多特权,建议使用 QQ 登录
喜欢我嘛?喜欢就按“ctrl+D”收藏我吧!♡