JVM垃圾回收机制

   Java内存分为堆内存(heap)和 Permanent区
    1、Java堆内存(heap):
         --是 JVM 用于分配 Java 对象的内存,包含活动对象和不可用对象
         --堆大小通常是在服务器启动时使用 java 命令中的 –Xms(最小) –Xmx(最大)标志来定义。
    2、Permanent区:
         --指内存的永久保存区域
         --是Sun JDK和HP JDK用来加载类(class)和Meta信息的专门的内存区
         --这个区域不归属Java堆内存(heap)范围
         --Class在被Loader时就会被放到此,如果Java应用很大,例如类(class)很多,那么建议增大这个区域的大小      来满足加载这些类的内存需求
         --通过–XX:PermSize=***M –XX:MaxPermSize=***M调整

 这里还有一个本地内存的概念:
·本地内存(native memory):
    --是 JVM 用于其内部操作的本地内存(非Java内存)
    --JNI 代码和第三方本地模块(例如,本地 JDBC 驱动程序)也使用本地内存
    --最大本地内存大小取决于以下因素:操作系统进程内存大小限制、已经指定用于 Java 堆的内存


 1、为什么要垃圾回收
    --JVM自动检测和释放不再使用的内存。
    --Java 运行时JVM会执行 GC,这样程序员不再需要显式释放对象。

 三、Java内存的调优参数
-Xmx1024m:
    设置JVM最大可用内存为1024M。

-Xms1024m:
    设置JVM促使内存为1024M。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。

-Xmn512m:
    设置年轻代大小为512M。(持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。)

-Xss128k:
    设置每个线程的堆栈大小。这个值可以根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。

-XX:NewRatio=4
    设置年轻代(包括Eden和两个Survivor区)与年老代的比值(总的大小是Xms的值)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。
    举个例子,-Xms 设置为 1024m,-Xmx 也设置为 1024m的情况下:
      ·年轻代 = 1024M/5 = 204.8M
      ·年老代 = 1024M/5*4 = 819.2M
    如果-Xms和-Xmx的值设置的不一样,可以添加 -XX:MinHeapFreeRatio=<minimum> 和 -XX:MaxHeapFreeRatio=<maximum> 参数,使内存的大小能够在 大于 -Xms 和 小于 -Xmx 之间的范围内自动调整,所以内存中会有Virtual的空间(我是这样理解的,不是太清楚,这里需要大家指教)

英文原文如下:http://java.sun.com/docs/hotspot/gc1.4.2/#3. Sizing the Generations|outline


    By default, the virtual machine grows or shrinks the heap at each collection to try to keep the proportion of free space to live objects at each collection within a specific range. This target range is set as a percentage by the parameters -XX:MinHeapFreeRatio=<minimum> and -XX:MaxHeapFreeRatio=<maximum>, and the total size is bounded below by -Xms and above by -Xmx .

-XX:SurvivorRatio=4:
    设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6

-XX:MaxPermSize=16m:
    设置持久代大小为16m。

-XX:MaxTenuringThreshold=0:
    设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。


 1、内存溢出
    内存溢出发生在这种状况下:Java内存完成Minor GC 之后想要把还存活的对象放到 Old区 里,但是这时Old区 已经满了,同时 Permanent区也已经放不下存活的对象。这时就会产生 OOM 错误。

2、内存泄露
    在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是有被引用的,即在有向树形图中,存在树枝通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。
    找到一个例子:

    “这里引用一个常看到的例子,在下面的代码中,循环申请Object对象,并将所申请的对象放入一个Vector中,如果仅仅释放对象本身,但因为Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。

    因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。


    Vector v = new Vector(10);      
    for (int i = 1; i < 100; i++)      
    {      
     Object o = new Object();      
     v.add(o);      
     o = null;      
    }//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。     

实际上这些对象已经是无用的,但还被引用,GC就无能为力了(事实上GC认为它还有用),这一点是导致内存泄漏最重要的原因。”


对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理heap中的所有对象。通过这种方式确定哪些对象是“可达的”,哪些对象是“不可达的”。当GC确定一些对象为“不可达”时,GC就有责任回收这些内存空间。当然,程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值