转!!Java虚拟机堆的内存分配和回收

Java内存分配和回收,主要就是指java堆的内存分配和回收。java堆一般分为2个大的区域,一块是新生代,一块是老年代。在新生代中又划分了3块区域,一块eden区域,两块surviver区域。一般称为from surviver和to surviver。这些区域的大小可以自己指定。比如:(-Xms20M 表示可用堆内存大小;-Xmx40M 表示最大堆内存,在堆内存大小不够时,会扩展到最大堆内存;-Xmn10M 表示新生代内存大小)。

新生代中的对象会在eden区域分配,然后eden区域的内存不够对象分配的时候,会发生一次minor GC。这时候,会把from surviver和eden区域的存活的对象复制到to surviver区域中,这次的to surviver区域变成了下次的form surviver。那么survier区域和eden区域如何按比例划分呢?由于java中很多对象都是朝生夕死的,被分配出来后,马上就会被垃圾回收,存活下来的对象很少,而存活下来的对象都会到surviver区域,所以sun公司觉得surviver区域太大不好,surviver区域大了,eden就小了,这样分配内存的空间就小了。所以sun公司默认surviver 区域和eden区域的比例为 from surviver :to surviver : eden为1:1:8。

那么大家会觉得,surviver区域的对象每次Minor GC都会存活下来,那么就会越积越多,会不会导致surviver区域存不下呢?答案时,确实会存不下,所以老年代这时候出场了。

surviver区域的对象,在经过若干次Minor GC之后,会升级成为老年代对象,从而进入老年代。jvm默认时15次gc,新时代还存活就进入老年代。当然,也有可能surviver区域都没有等到15次,surviver却满了,不用担心,这时候jvm会把平均年龄偏大的对象,统统送入老年代中。

可能大家还有疑问,如果一上来新生成的对象非常大,eden区这小船装不下会怎么办?那也没问题,直接就升级啦,成为老年人啦。不过老年人也是会越来越多的,jvm当然不会容忍这些尸体没人收变成木乃伊,当然要回收它们啦。当老年代内存不够分配的时候,这时候系统就会发生一次FULL GC,把老年代的垃圾也回收了。

在java虚拟机中,新生代和老年代的垃圾回收是分开的。java虚拟机提供给我们好几个垃圾回收器选择。

新生代收集器:

1.Serial收集器,单线程收集器,采用复制算法,由于单线程,所有在java服务器端开发中,肯定不会去用它。

2.ParNew收集器,是Serial的多线程版本,采用复制算法,可以说是java服务器端首选收集器。

3.Parallel Scavenge收集器,多线程,采用复制算法,此收集器最大的特点在可控制垃圾回收的吞吐量,此垃圾收集器适用于非实时和用户交互的服务器,适用于后台跑算法,跑job的服务器。

老年代收集器:

1.Serial old, Serial的老年版本。单线程的,采用标记-整理算法,很遗憾,同样不适合服务器中使用。

2.Parallel old,Parallel Scavenge的老年版本。多线程,标记-整理算法,此收集器和Parallel Scavenge特点一样,这2种收集器搭配,对于跑job的服务器来说,是很不错的,不过还的侃实际应用来配置,万一job任务的时间间隔很短,这时候在gc,可能就有问题,所以也不能一味最求吞吐量。

3.cms收集器,标记-清除算法,此收集器特点是,垃圾回收停顿时间短,重视服务器响应速度,给用户带来好的体验。

最后是新生代和老年代通吃的收集器,G1收集器。G1可以说非常强悍,除了吞吐量需求大的,其它的都可以被g1代替了。总之,以后服务器要体验好的,就用g1收集器,要吞吐量大的就用Parallel套装。

时间: 2024-10-26 06:53:33

转!!Java虚拟机堆的内存分配和回收的相关文章

Java虚拟机7:内存分配原则

http://www.cnblogs.com/xrq730/p/4841177.html 前言 对象的内存分配,往大的方向上讲,就是在堆上分配,少数情况下也可能会直接分配在 老年代中,分配的规则并不是百分之百固定的,其细节决定于当前使用的是哪种垃圾收集器组合,当然还有虚拟机中与内存相关的参数.垃圾收集器组合一般就是 Serial+Serial Old和Parallel+Serial Old,前者是Client模式下的默认垃圾收集器组合,后者是Server模式下的默认垃圾收集器组合,文章使用对比学

java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项技术当做Java语言的伴生产物.事实上GC的历史远远比Java来得久远,在1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期,人们就在思考GC需要完成的3件事情:哪些内存需要回收?什么时候回收?怎么样回收? 经过半个世纪的发展,目前的内存分配策略

java虚拟机(3)--内存分配与回收策略

三.内存分配与回收策略 1.1 Minor GC 和 Full GC Minor GC:发生在新生代上,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快. Full GC:发生在老年代上,老年代对象其存活时间长,因此 Full GC 很少执行,执行速度会比 Minor GC 慢很多. 1.2 内存分配策略 1.2.1            对象优先在 Eden 分配 大多数情况下,对象在新生代 Eden 区分配,当 Eden 区空间不够时,发起 Minor

Java深入 - Java 内存分配和回收机制-转

Java的GC机制是自动进行的,和c语言有些区别需要程序员自己保证内存的使用和回收. Java的内存分配和回收也主要在Java的堆上进行的,Java的堆中存储了大量的对象实例,所以Java的堆也叫GC堆. Java在垃圾收集的过程中,主要用到了分代收集算法,我会先讲一下常用垃圾收集算法. 常用垃圾收集算法 1. 标记-清除算法 这种垃圾收集算法思路非常简单,主要是首先标记出所有需要回收的对象,然后回收所有需要回收的对象. 但是有一个明显的缺点,采用这种算法之后会发现内存块回收之后就不连续了,这就

Java GC 机制与内存分配策略

收集算法是内存回收的方法论,垃圾收集器是内存回收的具体实现 自动内存管理解决的是:给对象分配内存 以及 回收分配给对象的内存 为什么我们要了解学习 GC 与内存分配呢? 在 JVM 自动内存管理机制的帮助下,不再需要为每一个new操作写配对的delete/free代码.但出现内存泄漏和溢出的问题时,如果不了解虚拟机是怎样使用内存的,那么排查错误将是一项非常艰难的工作. GC(垃圾收集器)在对堆进行回收前,会先确定哪些对象"存活",哪些已经"死去".那么就有了对象存活

java学习-----jvm的内存分配及运行机制

VM运行时数据区域: 根据<Java虚拟机规范(第二版)>的规定,JVM包括下列几个运行时区域: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的

java\c程序的内存分配

JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机.只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行.本文首先简要介绍从Java文件的编译到最终执行的过程,随后对JVM规格描述作一说明. 一.Java源文件的编译.下载.解释和执行 Java应用程序的开发周期包括编译.下载.解释和执行几个部分.Java编译程序将Java源程序翻译为JVM可执行代码?字节码.这一编译过程同C/C++的编译有

JAVA垃圾收集机制与内存分配

引言 垃圾收集技术并不是Java语言首创的,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.垃圾收集技术需要考虑的三个问题是: 哪些内存需要回收? 什么时候回收? 如何回收? http://segmentfault.com/a/1190000002931555 中讲到java内存运行时区域的分布,其中程序计数器,虚拟机栈,本地方法区都是随着线程而生,随线程而灭,所以这几个区域就不需要过多考虑回收问题.但是堆和方法区就不一样了,只有在程序运行期间我们才知道会创建哪

JAVA 垃圾收集器与内存分配策略

引言 垃圾收集技术并不是Java语言首创的,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.垃圾收集技术需要考虑的三个问题是: 哪些内存需要回收 什么时候回收 如何回收 http://my.oschina.net/jiangmitiao/blog/470426 中讲到java内存运行时区域的分布,其中程序计数器,虚拟机栈,本地方法区都是随着线程而生,随线程而灭,所以这几个区域就不需要过多考虑回收问题.但是堆和方法区就不一样了,只有在程序运行期间我们才知道会创建哪