Java的内存结构(Memory Structure)和垃圾收集(Garbage Collection)图解

原创 2012年04月13日 02:48:41

 

JVM 内存包含如下几个部分:

  • Heap Memory 存放Java对象
  • Non-Heap Memory 存放类加载信息和其它meta-data
  • Other 存放JVM 自身代码等

在JVM启动时,就已经保留了固定的内存空间给Heap内存,这部分内存并不一定都会被JVM使用,但是可以确定的是这部分保留的内存不会被其他进程使用。这部分内存大小由 -Xmx 参数指定。而另一部分内存在JVM启动时就分配给JVM,作为JVM的初始Heap内存使用。影响这个的参数是 -Xms

默认空余堆内存小于40%时,JVM 就会增大堆直到-Xmx的最大限制,可以由-XX:MinHeapFreeRatio指定。
默认空余堆内存大于70%时,JVM 会减少堆直到-Xms的最小限制,可以由-XX:MaxHeapFreeRatio指定。

可以通过-XX:MaxPermSize设置Non-Heap大小.

GC 的年代划分

如果 -Xms指定的值比-Xmx的小,那么两者的差值就是Virtual内存值。随着程序的运行,Eden区、 Tenured区和Perm区会逐渐使用保留的Virtual空间。

JVM内存模型中Heap区分两大块,一块是 NEW Generation,另一块是Old Generation. 在NewGeneration中,有一个叫Eden的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from,to),它们的大小总是一样,它们用来存放每次垃圾回收后存活下来的对象。在OldGeneration中,主要存放应用程序中生命周期长的内存对象。在NewGeneration块中,垃圾回收一般用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个SurvivorSpace, 当Survivor Space空间满了后, 剩下的live对象就被直接拷贝到OldGeneration中去。因此,每次GC后,Eden内存块会被清空。在OldGeneration块中,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求.
垃圾回收分多级,0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾;1级或以上为部分垃圾回收,只会回收NEW中的垃圾,内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。

还有个Permanent Generation,主要用来放JVM自己的反射对象,比如类对象和方法对象等。关于这个区,它还提供String pool,看下面的例子:

String first = "abc"; 
String second = new String ("abc");

第一个对象存贮在Permanent Generation,而第二个对象存储在Heap里面。所以:

String s = "abc";
String p = "abc";

对象s和p指向同一个对象,这样效率大大提高。

 

内存申请过程如下:

  1. JVM 会试图为相关Java对象在Eden中初始化一块内存区域
  2. 当Eden空间足够时,内存申请结束。否则到下一步
  3. JVM 试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区
  4. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区
  5. 当OLD区空间不够时,JVM 会在OLD区进行完全的垃圾收集(0级)
  6. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”


具体算法请参考:JDK5.0中JVM堆模型、GC垃圾收集详细解析


参考:

  • http://www.yourkit.com/docs/kb/sizes.jsp
  • http://blog.csdn.net/sfdev/article/details/4483442
  • http://longdick.iteye.com/blog/473866
  • http://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html

java堆空间(内存)

当Java程序开始运行时,JVM会从操作系统获取一些内存。JVM使用这些内存,这些内存的一部分就是堆内存。堆内存通常在存储地址的底层,向上排列。当一个对象通过new关键字或通过其他方式创建后,对象从堆...
  • u010760179
  • u010760179
  • 2014年07月15日 09:34
  • 1854

java堆内存的划分

根据对象的存活率(年龄),Java对内存划分为3种:新生代、老年代、永久代1、新生代: 比如我们在方法中去new一个对象,那这方法调用完毕后,对象就会被回收,这就是一个典型的新生代对象。 现在的商业...
  • liudezhicsdn
  • liudezhicsdn
  • 2016年04月04日 17:57
  • 1094

Java 对象在堆中的内存结构

翻译人员: 铁锚 翻译日期: 2013年11月8日 原文链接:  What do Java objects look like in memory during run-time? 我们知道,函数每...
  • renfufei
  • renfufei
  • 2013年11月09日 19:09
  • 20602

Java虚拟机详解----JVM内存结构

http://www.cnblogs.com/smyhvae/p/4748392.htm 主要内容如下: JVM启动流程JVM基本结构内存模型编译和解释运行的概念   ...
  • bluetjs
  • bluetjs
  • 2016年10月20日 17:10
  • 7330

JVM内存结构图解

一 真实系统中的概念   JVM(Java Virtual Machine),顾名思义是对真实计算机系统的模拟,正因如此才能屏蔽物理机器的变化,从而实现“一次编译,到处运行”。   相信很多Jav...
  • coffeelifelau
  • coffeelifelau
  • 2016年09月14日 08:44
  • 1524

(3) Java内存结构

Java的运行时数据区,也就是Java的内存结构(Java Structure),但注意区分Java的内存模型(Java Memory Model,JMM),JMM现在我还没仔细去研究过,有兴趣的同学...
  • a327369238
  • a327369238
  • 2016年08月02日 15:49
  • 1062

深入理解java虚拟机(一):java内存区域(内存结构划分)

图一:java内存结构划分 由上图可知,java内存主要分为6部分,分别是程序计数器,虚拟机栈,本地方法栈,堆,方法区和直接内存,下面将逐一详细描述。 1、程序计数器 线程私有,即每个线程都会有一个...
  • MINEZHANGHAO
  • MINEZHANGHAO
  • 2014年02月18日 17:45
  • 20067

也谈谈Java的垃圾收集(garbage collection)

垃圾收集是Java语言非常显著的特点,不像C语言那样,老是要考虑什么数字的越界什么的。什么是垃圾(garbage)呢?“An object is considered garbage when it ...
  • autofei
  • autofei
  • 2011年04月21日 12:48
  • 10783

Java中的垃圾回收是如何工作的?(How Garbage Collection works in Java)

注:此文是在blogspot(被墙)上看到的,能翻墙的同学们自己去看(点此此处), 顺道可以看看一些其他的资料;不能翻墙的同学在此将就将就。 我读过许多关于Java垃圾回收的文章,其中...
  • redhat456
  • redhat456
  • 2011年09月22日 21:27
  • 3758

关于JAVA中的Garbage Collection和finalize()

关于JAVA中的Garbage Collection和finalize() Java的内存释放涉及到Garbage Collection的概念,那么到底什么是Garbage Collection呢?中...
  • youhaodeyi
  • youhaodeyi
  • 2005年12月16日 13:37
  • 2905
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java的内存结构(Memory Structure)和垃圾收集(Garbage Collection)图解
举报原因:
原因补充:

(最多只允许输入30个字)