`
cary
  • 浏览: 85590 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

关于GC垃圾回收〔网络整理,并非原创〕

    博客分类:
  • J2EE
阅读更多
JVM配置参数中文说明:
-----------------------------------------------------------------------
1、-Xmixed           mixed mode execution (default)
混合模式执行

2、-Xint             interpreted mode execution only
解释模式执行

3、-Xbootclasspath:<directories and zip/jar files separated by ;>
      set search path for bootstrap classes and resources
设置zip/jar资源或者类(.class文件)存放目录路径

3、-Xbootclasspath/a:<directories and zip/jar files separated by ;>
      append to end of bootstrap class path
追加zip/jar资源或者类(.class文件)存放目录路径

4、-Xbootclasspath/p:<directories and zip/jar files separated by ;>
      prepend in front of bootstrap class path
预先加载zip/jar资源或者类(.class文件)存放目录路径

5、-Xnoclassgc       disable class garbage collection
关闭类垃圾回收功能

6、-Xincgc           enable incremental garbage collection
开启类的垃圾回收功能

7、-Xloggc:<file>    log GC status to a file with time stamps
记录垃圾回日志到一个文件。

8、-Xbatch           disable background compilation
关闭后台编译

9、-Xms<size>        set initial Java heap size
设置JVM初始化堆内存大小

10、-Xmx<size>        set maximum Java heap size
设置JVM最大的堆内存大小

11、-Xss<size>        set java thread stack size
设置JVM栈内存大小

12、-Xprof            output cpu profiling data
输入CPU概要表数据

13、-Xfuture          enable strictest checks, anticipating future default
执行严格的代码检查,预测可能出现的情况

14、-Xrs              reduce use of OS signals by Java/VM (see documentation)
通过JVM还原操作系统信号

15、-Xcheck:jni       perform additional checks for JNI functions
对JNI函数执行检查

16、-Xshare:off       do not attempt to use shared class data
尽可能不去使用共享类的数据

17、-Xshare:auto      use shared class data if possible (default)
尽可能的使用共享类的数据

18、-Xshare:on       require using shared class data, otherwise fail.
尽可能的使用共享类的数据,否则运行失败

The -X options are non-standard and subject to change without notice.


管理内存查看可HEAP的查看可以利用JPROFILE来跟踪其变化,以达到找到其性能的瓶颈处

深入观察GC
我们要计算的统计如下所示“
● 考虑的运行的持续时间
● 收集总数
● 收集频率
● 收集所用最长时间
● 收集所用总时间
● 收集所用平均时间
● 收集的平均间隔
● 分配的字节总数
● 每次收集每秒分配的字节数
● 恢复的字节总数
● 每次收集每秒恢复的字节总数

Sun 1.4.2_03 JVM 以 -Xloggc:filename 运行默认的标记-清除收集器所生成的日志记录
要让垃圾收集(GC)回收程序不再使用的对象,对象的逻辑生命周期(应用程序使用它的时间)和对象拥有的引用的实际生命周期必须是相同的。在大多数时候,好的软件工程技术保证这是自动实现的,不用我们对对象生命周期问题花费过多心思。但是偶尔我们会创建一个引用,它在内存中包含对象的时间比我们预期的要长得多,这种情况称无意识的对象保留(unintentional object retention)

全局MAP造成的内存泄漏
无意识对象(unintentional object retention)保留最常见的原因是使用MAP将元数据与临时对象(transient object)相关联。假定一个对象具有中等生命周期,比分配它的那个方法调用的生命周期长,但是比应用程序的生命周期短,如客户机的套接字连接。需要将一些元数据与这个套接字关联,如生成连接的用户的标示。在创建SOCKET时是不知道这些信息的,并且不能将数据添加到SOCKET对象上,因为不能控制SOCKET类或者它的子类。这时,典型的方法是在一个全局MAP中存储这些信息。如SocketManager类所示:
Public class SocketManager{
Private Map<Socket,User> m = new HashMap<Socket,User>();

Public void setUser(Socket s,User s)
{
m.put(s,u);
}
Public User getUser(Socket s)
{
Return m.get(s);
}

Public void removeUser(Socket s)
{
m.remove(s);
}
}

SocketManager socketManager;
………
socketManager.setUser(socket,user);
这种方法的问题是元数据的生命周期需要与套接字的生命挂钩,但是除非准确地知道什么时候程序不在需要这个套接字,并记住从MAP中删除相应的映射,否则,SOCKET和USER对象将会永远保留在MAP中,远远超过响应了请求和关闭套接字的时间。这是阻止SOCKET和USER对象被垃圾收集,即使应用程序不会再使用它们。这些对象留下来不受控制,很容易造成程序在长时间运行后内存爆满。除了最简单的情况,在几乎所有情况下找出什么时候SOCKET不再被程序使用是一件很烦人和容易出错的任务,需要人工对内存进行管理。

找出内存泄漏
程序有内存泄漏的第一个迹象通常是它抛出一个OutOfMemoryError,或者因为频繁的垃圾收集而表现出糟糕的性能。幸运的是,垃圾收集可以提供能够用来诊断内存泄漏的大量信息。如果以-verbose:gc或者-Xloggc选项调用JVM,那么每次GC运行时在控制台上或者日志文件中会打印出一个诊断信息,包括它所花费的时间,当前堆使用情况以及恢复了多少内存。纪录GC使用情况并不具体有干扰性,因此如果需要分析内存问题或者调优垃圾收集器,在生产环境中默认启用GC日志是值得的。
有工具可以利用GC日志输出并以图形的方式将它显示出来,Jtune就是这样的一种工具。观察GC之后堆大小的图,可以看到程序内存使用的驱使。对于大多数程序来说,可以将内存使用分为两部:baseline使用和 current load使用。对于服务器应用程序,baseline使用就是应用程序在没有任何负荷、但是已经准备好接受请求时的内存使用,current load使用是在处理请求过程中使用的、但是在请求处理完成后会释放的内存。只要内存大体上是恒定的,应用程序通常会很快达到一个稳定的内存使用水平。如果在应用程序已经使用了其初始化并且负荷没有增加的情况下,内存使用持续增加,那么程序就可能在处理前面的请求时保留了生成的对象。

下面代码是基于MAP的内存泄漏的程序

Public class MapLeaker
{
Public ExecutorService exec = Executors.newFixedThreadPool(5);
Public Map<Task,TaskStatus> taskStatus = Collections.synchronizedMap(new HashMap<Task,TaskStatus>());
Private Random random = new Random();

Private enum TaskStatus{NOT_STARTED,STARTED,FINISHED};

Private class Task implements Runnable
{
Private int[] numbers = new int[random.nexInt(200)];

Public void run()
{
Int[] temp = new int[random.nexInt(1000)];
taskStatus.put(this,TaskStatus.STARTED);
doSomeWork();
taskStatus.put(this,TaskStatus.FINISHED);
}
}

Public Task newtTask()
{
Task t = new Task();
taskStatus.put(t,TaskStatus.NOT_STARRED);
return t;
}
}
上述程序确信存在内存泄漏后,内制的hprof工具也可完成这项工作。要使用hprof并让它跟踪内存使用,需要以-Xrunhprof.heap = sites 选项调用JVM.


编写对GC友好,又不泄漏的代码
1:使用更多生命周期短的,小的,不改变指向(immutable)的对象,编写清晰的代码。
出于懒惰也好,朴素的节俭意识也好,我们都习惯对一个变量重用在重用。但是…..
JAVA的垃圾收集器喜欢短生命周期的对象,对象如果在新生代内,在垃圾收集发生前死掉了,垃圾收集器就什么都不用做了。
频繁的NEW对象也导致更频繁的GC。大对象的分配效率更底,而且对非压缩算法的垃圾收集器,更容易造成碎片。
对象重用增加代码的复杂度,降低了可读性。所以呼吁,比如不要害怕为中间结果分配小对象。
2:将用完的对象设为NULL其实没什么作用
貌似很酷的把对象主动设为NULL的“好习惯”其实没什么用。JIT Compiler会自动分析LOCAL变量的生命周期。
只有一个例外情况,就是String[1024] foo 这种赤裸裸的数组。你需要主动的FOO[100]=NULL释放第100号元素,所以最好还是直接用ArrayList这些标准库算了。
3:避免显示GS-System.gc().
大家都知道System.gc()不好,full-gc浪费巨大,gc的时机把握不一定对等等,甚至-XX:+DisableExplicitGC的JVM参数来禁止它。
先用FindBugs 查一下所用到的全部第三方类库吧...
至少RMI 就会老实不客气的执行System.gc()来实现分布式GC算法。但我也不会用RMI啊。那EJB呢,EJB可是建在RMI上的。
如果无可避免,用-Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 (单位为微妙) 增大大GC的间隔(原默认值为1分钟),-XX:+ExplicitGCInvokesConcurrent 让System.gc() 也CMS并发执行。
4.继续千夫所指的finalize()

    大家也都知道finalize()不好,分配代价昂贵,释放代价更昂贵(要多走一个循环,而且他们死得慢,和他们相关联的对象也跟着死得慢了),又不确定能否被调用(JVM开始关闭时,就不会再进行垃圾收集),又不确定何时被调用(GC时间不定,即使system.gc()也只是提醒而不是强迫GC,又不确定以什么样的顺序调用,所以finalize不是C++的析构函数,也不像C++的析构函数。

   我们都知道啊,所以我从来都没使用。都是在显式的维护那些外部资源,比如在finally{}里释放。

5.WeakReference/SoftReference

   这是个平时不怎么会搭理,偶然知道了又觉得有用的Java特征。大家都知道Java里所有对象除int等基本类型外,都是Pass by Reference的指针,实例只要被一个对象连着,就不会被收集。
    而WeakReference就是真正意义上的C++指针,只是单纯的指向一个对象,而不会影响对象的引用计数。
    而SoftReference更特别,在内存足够时,对象会因为SoftReference的存在而不被收集,但内存不足时,对象就还是会被收集,怎么看都是做简单缓存的料子。代码如下:



  Foo foo = new Foo();
  SoftReference sr= new SoftReference(foo);
  Foo bar =  sr.get();
  如果foo已被垃圾收集,sr.get()会返回Null;

  另外还有一个ReferenceQueue的机制,使得对象被回收时能获得通知,比finalize()完全不知道GC何时会执行要聪明的多。



  ReferenceQueue rq = new ReferenceQueue();
  ref = new WeakReference(foo, rq);
  WeakReference cleaned = rq.pool();

  cleaned就是刚刚被GC掉的WeakReference。
分享到:
评论

相关推荐

    c#的GC垃圾回收机制详细讲解文档

    C#的垃圾回收机制(GC)是.NET框架中一个至关重要的特性,它负责自动管理和释放内存,从而减轻程序员的工作负担。GC的主要目标是回收不再使用的对象所占用的内存,以防止内存泄漏。在这个机制下,程序员无需手动管理...

    Java_GC垃圾回收调优指南

    ### Java GC垃圾回收调优指南 #### 概述 在Java开发过程中,垃圾回收(Garbage Collection, GC)是管理内存资源的关键技术之一。合理的GC配置可以显著提高应用程序的性能和稳定性。本指南旨在帮助开发者深入理解...

    JVM GC垃圾回收.pdf

    JVM GC垃圾回收.pdfJVM GC垃圾回收.pdfJVM GC垃圾回收.pdfJVM GC垃圾回收.pdfJVM GC垃圾回收.pdf

    java jstat 查看哪个进程频繁GC垃圾回收

    Java垃圾回收(Garbage Collection, 简称GC)是JVM(Java Virtual Machine)管理内存的重要机制。在Java应用程序运行过程中,如果发现并回收不再使用的对象,可以防止内存泄漏,确保程序稳定运行。当我们遇到应用...

    GC垃圾回收机制

    GC 按代回收垃圾也是出于性能考虑的;通常的对象都会在 0 代是被回收。 从代的角度看,大对象属于 2 代对象,因为只有在 2 代回收时才会处理大对象。当某代垃圾回收执行时,会同时执行更年轻代的垃圾回收。比如:当...

    JVM垃圾回收机制与GC性能调优

    Java虚拟机(JVM)的垃圾回收(GC)机制是Java程序高效运行的关键部分,它自动管理内存,释放不再使用的对象以避免内存泄漏。本文主要探讨JVM堆内存的结构和GC的工作原理,以及如何进行性能调优。 JVM堆是Java应用...

    [JAVA·初级]GC垃圾回收机制编程开发技术共14页.p

    【JAVA·初级】GC垃圾回收机制是Java编程中一个至关重要的概念,对于任何Java开发者来说,理解并掌握这一机制都是提升程序性能的关键。在Java中,内存管理主要依赖于垃圾回收器(Garbage Collector,简称GC),它...

    C#垃圾回收机制GC

    2. Compact(压缩):回收垃圾后,将存活对象移动到堆的起始位置,使其连续排列,以便更有效地利用内存空间。 在.NET中,GC执行过程会暂停所有线程,确保内存状态的一致性。它会查找各种类型的根,包括全局变量、...

    【ASP.NET编程知识】.Net的GC垃圾回收原理及实现.docx

    ".NET 的 GC 垃圾回收原理及实现" .NET 的 GC 垃圾回收原理及实现是 ASP.NET 编程知识的重要组成部分。垃圾回收(Garbage Collection)是指在 .NET Framework 中自动管理内存的机制,通过回收不再使用的对象来释放...

    GC.mmap-垃圾回收算法脑图

    GC总结

    第6节: GC垃圾回收-02

    **垃圾回收(GC)原理与实现** 垃圾回收是Java虚拟机(JVM)管理内存的重要机制,它自动识别并清理不再使用的对象,以避免内存泄漏。GC的主要目标是在不干扰程序正常运行的前提下,有效地回收内存资源。 ### **...

    java垃圾回收(gc)机制详解

    Java垃圾回收(GC)机制是Java编程语言中的一个重要特性,它自动管理程序的内存空间,负责识别并清除不再使用的对象,以防止内存泄漏。本文将深入探讨Java GC的工作原理、类型、过程以及优化策略。 一、Java垃圾...

    垃圾回收机制面试题·.docx

    垃圾回收并非随时都在进行,它的触发有一定的条件: - **空闲时间**:在系统空闲时,垃圾回收器会选择性地进行垃圾回收。 - **内存紧张**:当系统内存不足时,垃圾回收器会被强制启动。 #### 六、垃圾回收的方法...

    java垃圾回收(gc)机制详解.pdf

    Java垃圾回收(GC)机制是Java语言管理内存的自动化机制,它能够自动释放不再使用的内存空间,从而避免内存泄漏和程序崩溃等问题。在介绍Java GC机制之前,我们首先要了解垃圾回收的目的和意义。在任何程序中,内存...

    白话说java gc垃圾回收.docx

    Java垃圾回收(GC)是Java语言的一大特性,它自动化地管理程序内存,使得开发者无需手动进行内存分配和释放,从而避免了C/C++等语言中常见的内存泄漏问题。GC通过智能地识别并回收不再使用的对象,确保内存的有效...

    GC垃圾回收

    GC垃圾回收

    垃圾回收技术示例 垃圾回收技术示例

    垃圾回收(Garbage Collection, GC)是编程语言中用于自动管理内存的重要机制,尤其是在像Java、C#等语言中。这个技术示例旨在深入探讨垃圾回收的原理、工作流程以及在实际开发中的应用。 垃圾回收的基本目标是识别...

Global site tag (gtag.js) - Google Analytics