编写对GC友好,又不泄漏的代码_第1页
编写对GC友好,又不泄漏的代码_第2页
编写对GC友好,又不泄漏的代码_第3页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、编写对GC友好,又不泄漏的代码1.使用更多生命周期短的、小的、不改变指向(immutable)的对象,编写清晰的代码。     出于懒惰也好,朴素的节俭意识也好,我们都习惯对一个变量重用再重用。但是. Java的垃圾收集器喜欢短生命周期的对象,对象如果在新生代内,在垃圾收集发生前就死掉了,垃圾收集器就什么都不用做了。 现代JVM构建一个新对象只需要10个本地CPU指令,并不弱于C/C+。 (但垃圾收集没有压缩算法时会稍慢,更频繁的New对象也导致更频繁的GC)。 大对象的分配效率更低,而且对非压缩算法的垃圾收集器,更容易造成碎片。 对象重用增加了代码的复杂度,降低了可读性。

2、   所以有标题的呼吁,比如不要害怕为中间结果分配小对象。但编程习惯的改变也不是一朝一夕的事情。 2.将用完的对象设为NULL其实没什么作用。     貌似很酷的把对象主动设为Null 的"好习惯"其实没什么用,JIT Compiler会自动分析local变量的生命周期。    只有一个例外情况,就是String1024 foo 这种赤裸裸的数组,你需要主动的foo100=null释放第100号元素,所以最好还是直接用ArrayList这些标准库算了。 3.避免显式GC-System.gc()。    

3、大家都知道System.gc()不好,full-gc浪费巨大,gc的时机把握不一定对等等,甚至有-XX:+DisableExplicitGC的JVM参数来禁止它。     哈哈,但我还不会用System.gc()呢,不怕不怕。真的不怕吗? 先用FindBugs 查一下所用到的全部第三方类库吧. 至少RMI 就会老实不客气的执行System.gc()来实现分布式GC算法。但我也不会用RMI啊。那EJB呢,EJB可是建在RMI上的.     如果无可避免,用-Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.d

4、gc.server.gcInterval=3600000 (单位为微妙) 增大大GC的间隔(原默认值为1分钟),-XX:+ExplicitGCInvokesConcurrent 让System.gc() 也CMS并发执行。 4.继续千夫所指的finalize()     大家也都知道finalize()不好,分配代价昂贵,释放代价更昂贵(要多走一个循环,而且他们死得慢,和他们相关联的对象也跟着死得慢了),又不确定 能否被调用(JVM开始关闭时,就不会再进行垃圾收集),又不确定何时被调用(GC时间不定,即使system.gc()也只是提醒而不是强迫GC,又不 确定以什么样的顺

5、序调用,所以finalize不是C+的析构函数,也不像C+的析构函数。   我们都知道啊,所以我从来都没使用。都是在显式的维护那些外部资源,比如在finally里释放。 5.WeakReference/SoftReference   这是个平时不怎么会搭理,偶然知道了又觉得有用的Java特征。大家都知道Java里所有对象除int等基本类型外,都是Pass by Reference的指针,实例只要被一个对象连着,就不会被收集。    而WeakReference就是真正意义上的C+指针,只是单纯的指向一个对象,而不会影响对象的引用计数。  

6、60; 而SoftReference更特别,在内存足够时,对象会因为SoftReference的存在而不被收集,但内存不足时,对象就还是会被收集,怎么看都是做简单缓存的料子。代码如下:   Foo foo = new Foo();   SoftReference sr= new SoftReference(foo);   Foo bar =  sr.get();   如果foo已被垃圾收集,sr.get()会返回Null;   另外还有一个ReferenceQueue的机制,使得对象被回收时能获得通知,比finalize()完全不知道

7、GC何时会执行要聪明的多。   ReferenceQueue rq = new ReferenceQueue();  ref = new WeakReference(foo, rq);   WeakReference cleaned = rq.pool();   cleaned就是刚刚被GC掉的WeakReference。6.内存泄漏   java 不是有垃圾收集器了吗?怎么还泄漏啊,唬我啊?  嗯,此泄漏非比泄漏。C/C+的泄漏,是对象已不可到达,而内存又没有回收,真正的内存黑洞。  而Java的泄漏,则是因为各种原因,对

8、象对应用已经无用,但一直被持有,一直可到达。  总结原因无外乎几方面: 被生命周期极长的集合类不当持有,号称是Java内存泄漏的首因。这些集合类的生命周期通常极长,而且是一个辅助管理性质的对象,在一个业务事务运行完后,如果没有将某个业务对象主动的从中清除的话,这个集合就会吃越来越多内存,可以用WeakReference,如WeakHashMap,使得它持有的对象不增加对象的引用数。 Scope定义不对,这个很简单了,方法的局部变量定义成类的变量,类的静态变量等。 异常时没有加finally来释放某些资源,JDBC时代也是很普遍的事情。 另外一些我了解不深的原因,如:Swing里的Listener没有显式remove;内部类持有外部对象的隐式引用;Finalizers造成关联对象没有被及时清空等。 内存泄漏的检测 有不少工具辅助做这个事情的,如果手上一个工具也没有,可以用JDK自带的小工具: 看看谁占满了Heap?用jmap可以显示运行程序中对象的类型,个数与所占的大小先用jps 找到进程号,然后jmap -histo pid 显示或 jmap -dump:file=heap

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论