在实际编程中对内存的优化

 Java Web 2.0架构开发与项目实战主要内容介绍http://www.china-pub.com/48443&ref=ps

应用Java开发的系统给人的印象是占内存,其实从理论上来讲,Java开发的系统并不比其他语言开发出来的系统更占用内存,这就需要在编程时注意优化内存。

1)不要使用new Boolean()

在许多应用场景中,Boolean类型是必须的,比如JDBCboolean类型的setget都是通过Boolean封装传递的,大部分ORM也是用Boolean来封装boolean类型,例如:

ps.setBoolean("isClosed",new Boolean(true));

通常这些系统中构造的Boolean实例的个数是相当多的,所以系统中充满了大量Boolean实例小对象,这是相当消耗内存的。Boolean类实际上只要两个实例就够了,一个true的实例,一个false的实例。Boolean类提供两了个静态变量:

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

在实际编程序中需要的时候只要取这两个变量就可以了,例如:

ps.setBoolean("isClosed",Boolean.TRUE);

如果要根据一个boolean变量来创建一个Boolean,可以使用Boolean提供的静态方法: Boolean.valueOf() ,例如:

ps.setBoolean("isClosed",Boolean.valueOf(isClosed));

 因为valueOf的内部实现是:return (b ? TRUE : FALSE),所以可以节省大量内存。

2)不要使用new Integer

 和Boolean类似,java开发中使用Integer封装int的场合也非常多,并且通常用int表示的数值通常都非常小。Integer类缓存了-128127256个状态的Integer,如果使用Integer.valueOf(int i),传入的int范围正好在此内,就返回静态实例。这样如果我们使用Integer.valueOf代替new Integer的话也将大大降低内存的占用。

3)用StringBuffer代替字符串相加。

4)过滥使用哈希表,有一定开发经验的开发人员经常会使用hash表(hash表在JDK中的一个实现就是HashMap)来缓存一些数据,从而提高系统的运行速度。比如使用HashMap缓存一些物料信息、人员信息等基础资料,这在提高系统速度的同时也加大了系统的内存占用,特别是当缓存的资料比较多的时候。其实我们可以使用操作系统中的缓存的概念来解决这个问题,也就是给被缓存的分配一个一定大小的缓存容器,按照一定的算法淘汰不需要继续缓存的对象,这样一方面会因为进行了对象缓存而提高了系统的运行效率,同时由于缓存容器不是无限制扩大,从而也减少了系统的内存占用。现在有很多开源的缓存实现项目,比如ehcacheoscache等,这些项目都实现了FIFOMRU等常见的缓存算法。

5)避免过深的类层次结构和过深的方法调用。因为这两者都是非常占用内存的(特别是方法调用更是堆栈空间的消耗大户)。

6)变量只有在用到它的时候才定义和实例化。

7)尽量避免使用static变量,类内私有常量可以用final来代替。

8)尽早释放无用对象的引用。如:

User user=new User();

应用user对象之后,应设置user = null,当使用对象user之后主动将其设置为空,这种作法在B/S系统的服务中很重要,由于服务器同时要服务成千上万个用户访问,这样有可能会创建多个user对象,如果user是方法的返回值,不要做这样的处理,否则你从该方法中得到的返回值永远为空,而且这种错误不易被发现、排除。在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。另外,对象的释放是由GC决定和执行的。在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线的方法确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为,GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。所以可以把不在引用的对象设置为null,以建议GC回收这些对象。对于程序员来说,GC基本是透明的,不可见的。虽然,我们只有几个函数可以访问GC,例如运行GC的函数System.gc(),但是根据Java语言规范定义, 该函数不保证JVM的垃圾收集器一定会执行。因为,不同的JVM实现者可能使用不同的算法管理GC。通常,GC的线程的优先级别较低。JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。但通常来说,我们不需要关心这些。除非在一些特定的场合,GC的执行影响应用程序的性能,例如对于基于Web的实时系统,如网络游戏等,用户不希望GC突然中断应用程序执行而进行垃圾回收,那么我们需要调整GC的参数,让GC能够通过平缓的方式释放内存,例如将垃圾回收分解为一系列的小步骤执行,Sun提供的HotSpot JVM就支持这一特性。

9)尽量少用finalize函数。它会加大GC的工作量。

10)尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其自类的构造器时造成不必要的内存资源浪费。

11)尽量避免强制系统做垃圾内存的回收,增长系统做垃圾回收的最终时间。

12)尽量避免显式申请数组空间。

13)尽量做远程方法调用类应用开发时使用瞬间值变量,除非远程调用端需要获取该瞬间值变量的值。

14)尽量在合适的场景下使用对象池技术以提高系统性能。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值