Java性能小技巧
英文原文:xmlandmore,编译:ImportNew - 朱伟杰
局部决定整体。一个应用的整体性能取决于每个组件的性能。下面是一些帮助你提高应用性能的Java编程技巧:
编程技巧 | 原因及策略 | ||||
避免重复创建对象 | 为什么:
怎么做:
| ||||
避免循环引用 | 为什么:
怎么做:
| ||||
使用==操作符来替代equals(Object)方法 | 为什么:
怎么做:
| ||||
清除无用的对象的引用 | 为什么:
怎么做:
| ||||
避免使用finalizer | 为什么:
| ||||
避免使用引用对象 | 为什么:
| ||||
避免使用对象池 | 为什么:
| ||||
选择好的算法和数据结构 | 为什么:
| ||||
避免使用System.gc | 为什么:
| ||||
避免使用太多的线程 | 为什么:
| ||||
避免使用竞争锁 | 为什么:
| ||||
避免不需要的异常 | 为什么:
| ||||
避免使用大对象 |
为什么:
|
参考书籍
英文原文:xmlandmore,编译:ImportNew - 朱伟杰
几个问题:
1.“重复利用一个对象,而不是在每次需要的时候都去创建一个功能一样的对象”这个和“对象池”思想有点类似吧,这样不和后面的矛盾吗?
2.“一组相互引用的对象,如果他们没有被其他对象直接引用的话”
实际jvm实现中又不是用引用技术进行垃圾标记的,这有什么问题?
3.清除无用的对象的引用
这里的例子貌似是Effective Java中的,记得这本书和JavaOne上强调的是,这些数据结构中不要忘记类似的清理,方法中的局部变量赋值为null大多数不需要的。
1、这里的重复使用是针对于局部的变量,比如一个for循环里使用的变量,而“对象池”更多的是一个全局的概念
2、即使不是用引用技术进行垃圾标记,但是也需要通过引用来判断一个对象是否需要回收。
3、这里的局部变量通过return result逸出到外部,所以需要这样处理
1.估计要具体问题具体分析吧。而且jvm专门优化了对小对象的分配,用不了多少条指令,在young区的回收也很方便。这方面感觉更多的应该从代码易读性方面考虑。
2.看原文中”一组相互引用的对象,如果他们没有被其他对象直接引用的话,它们会变得不可达,这样会导致它们一直都保留在内存里。“这明显是错误的吧。如果没有从root指向它们的引用,自然就是垃圾,这个很容易测试出来。
3.这里return的实际是”成员“,就是我上面留言中提到的情形,也是Effective Java中提到的例子。
感觉本文不算很好,把一些特殊问题当做一般化概念提出来了,比如”使用==操作符来替代equals(Object)方法“、”清除无用的对象的引用“等适用于特殊条件的操作当做条目提出来的时候,可能会对读者造成误导。
1、这个问题的关键不在于示例代码上,而在于“更少的对象会需要更少的垃圾回收”,对于这个示例而言可能没多大的性能影响,但是这个说法应该是对的。
2、假设有Root->A->Parent->Child,Child->Parent这样的引用,如果A被设置为Null,那么Parent和Child没有被Root引用,但是自身又相互引用,这种情况下如果采用的是引用计数器的方式来判断的话,这两个对象就没法回收了。如果是根据Root引用的话,它们就会被回收。所以,这句话不能绝对的说是错的。
3、这个地方虽然是“成员”,但是它的引用逸出带外面了,如果调用这个方法的地方一直保持这个引用的话,那么这个“成员”就不会被回收。
这篇文章虽然有些不合适的地方,但是读者可以透过它去思考垃圾回收背后的一些机制,就如同我们现在在讨论一样。正所谓“仁者见仁智者见智”,这篇文章至少能够提供给读者一些思考的空间,这样的文章才是难能可贵的。
2.没记得哪个jvm用到引用计数了,这个我回头再确认一下。好久不用java了。
3.说的不是一回事。我说的是局部变量比如{ Object obj = new Object();}这种obj一般不需要特殊处理的。 文章中举的那个例子,其实和你的说法也不尽一致,这个可以参考下effective java,里面提到了为什么不清空有问题。外不外带不是关键。
呵呵,不是否定文章的价值,而是不思考当金科玉律背诵条目的读者会不少。写文章的时候可能需要注意的一个问题是,论点是不是精确限定了边界,例子是不是精确论证论点的。
2、引用计数只是我举的一种例子,实际应该没有这样用的。
3、如果是局部变量的话,这个地方确实是没有必要的。文章里关于边界性确实没有很好的界定。
您的考虑确实很周到,我翻译的时候完全没考虑到这些问题。非常感谢!
elements[size] == null; // 清除无用对象的引用
这个代码多了一个=
已经更正,非常感谢!
避免循环引用 这个不对吧? 那你说hibernate里面那么多的循环依赖就不回收了?
java 垃圾回收不是说相互强引用就不回收了,还必须要被GC roots对象引用才行。
您好,对于目前的JVM而言,这个观点是不对的,可以参考zangxt的回复。
关于您的说法:用==代替equal ,这一说法有问题吧?!equal本来从Object那里来,不同行子类不同实现,而字符串中的equal是比较字符而不比较引用,但是其他继承Object的子类并不一定跟String同样的实现,但您说:“当且仅当a == b 的时候才会有a.equals(b) ” —>> 那么如果我这儿写:String a = new String(“aa”);String b = new String(“aa”); a == b为false,而a.equals(b)为true,楼主,这说法怎么破?您这么一说,很多初学者信以为真然后都用==代替了equals,然后他们就悲剧了