今天我为大家分享的内容是《利于GC的编码》,内容比较简单,有不合理的地方欢迎指正。

一、利于GC的编码

JVM每个java程序员都认识,这里不做拓展;

二、JVM的特点

JVM具有高效的创建和回收对象的能力,喜好小对象,生命周期短,不改变指向的对象。 对生命周期短的对象,GC回收高效(新生代的复制算法,不需要扫描和复制就能回收)

切勿滥用对象池,否则对象池不一定能提高性能,反倒会影响 GC效率。一般程序猿都有一个误区,总是动不动就使用对象池作为缓冲。 什么时候用对象池?
创建对象的开销较大。 涉及到DB/IO/Network等紧张资源的对象创建。 对象池生命周期长,每次full gc都要处理(mark, compact, etc) , 涉及多线程共享问题,对象池可能带来同步等额外开销 容易产生内存泄漏。

三、hashMap编码

当使用HashMap时,尽量减少resize。 减少resize可以避免没有必要的array copying, gc碎片等问题。一起来看看hashMap源码。 新增元素的源码 image
达到阀值时进行了resize,HashMap翻倍 image
扩容后,HashMap会重新将元素按照hash算法插入 image
在new ArrayList时,尽量估算size,在创建的时候把size确定 ,如果依赖于动态分配,每次分配是最大长度的1.5倍,会造成资源浪费,也会影响GC的效率

对于只需要顺序访问,不需要随机访问的List,用LinkedList代替ArrayList ,因为LinkedList本质是链表;

所以我们尽量预测集合的容量。

四、内存泄漏

java不是有自动回收内存吗?不需要关注内存呀? 错,大错特错。

用通俗的话来描述一下Java的内存泄漏:在有限的空间内,存满了有用和无用的东西,GC无法分清哪些是有用的,哪些是没有用的,无法进行清理。

Java内存泄漏类型 (自己划分,不一定权威)

Java内存泄漏的几个经典原因

1. 对象定义在错误的范围

接下来看一个例子 image

2. 异常(Exception)处理不严谨,导致资源没有释放

例如DB操作时菜鸟经常犯的错误,例子如下 image

3. 没有控制好集合数据的大小

4. String 的substring导致内存泄漏

1.5的问题,我本地的1.6版本已经不存在该问题,1.7以后肯定是没有问题

错误写法

image

正确写法

image

  1. 减少“+”去拼接String ,尽量使用StringBuilder和StringBuffer;
  2. GC调优 (不做拓展) – 分配合适的堆大小 – 采用合适的垃圾回收器;
  3. 良好的编程习惯 – 尽量少用静态对象发量;
  4. 避免集中创建对象尤其是大对象;
  5. 不要在经常调用的方法中创建对象;
  6. 应该定义为局部变量,则不要定义为类的变量 ;
  7. 预估好数据库中查询出的数据量,数据太多,造成OOM 的异常。

本文档来自支付产品技术交流群的聊天记录整理,由志愿者整理并发布到本网站。如需要及时收到来自支付产品技术交流群的最新消息,请扫码关注“凤凰牌老熊”的微信公众号。 本群面向支付行业的有经验(2年以上)的产品经理、软件工程师、架构师等,提供交流平台。如想加入本群,请在本文评论中留言(不公开),说明所在的公司、负责的工作、入群分享的主题和时间。