Java小对象的解决之道——对象池(Object Pool)的设计与应用

一、概述

面向对象编程是软件开发中的一项利器,现已经成为大多数编程人员的编程思路。很多高级计算机语言也对这种编程模式提供了很好的支持,例如C++Object PascalJava等。曾经有大量的软件工程师使用C语言作为他们的谋生工具,随着面向对象的深入人心,微软公司也对其C语言进行了扩充,形成了C++语言,全面支持面向对象的软件开发模式。

“面向对象”的主角即是“对象”,其良好的可充用性和对数据逻辑的封装成了它在当今计算机软件开发领域一炮走红的主要因素。程序开发人员也正是利用了对象的这些特点在程序中大量创建对象,以至于他们往往忽略了这种创建对象以及以后销毁对象是带来的系统开销之大是多么不可想象。特别是对于现在十分流行的Java语言,这更是一个不能避免的问题。下面,我们就从分析Java的内存管理机制入手,首先看看造成Java程序有些时候效率低下的症结所在,然后再讨论一下如何利用编程技巧改进我们的程序。

 

二、Java的内存管理机制

1、垃圾回收与小对象

C/C++语言相比,Java语言不需要程序员显式地为每个对象定义“析构函数”,Java虚拟机(JVMJava Virtual Machine)会利用自身的“垃圾回收”机制在后台启动一个守护线程负责对不再被利用的对象进行内存清理工作。这种思路并不是Java的“原创”,早在20世纪60年代,自动垃圾回收就已经被提出并在其他语言中得到了应用。所有的垃圾回收机制都遵循一条统一的原则“利用不同的方法来判定程序中不再被引用的对象,销毁它们释放内存。”其不同之处也就在于“判定”过程(Java使用的是一种称为“可达性分析”的方法,这里不作主要介绍)。

Java的自动垃圾回收机制确实可以让程序员从繁重的开发工作中得以解脱,使他们不再关心自己曾经创造的对象在不用时如何处理,从而将精力主要集中在业务逻辑的开发上。但是一句富有哲理的中国的老话在它身上再次应验:“Java垃圾回收是一把双刃剑!”

首先我们注意到,“垃圾回收”是JVM支持的一项后台工作,是“时事”进行的。当它发现某个对象处于“不可达”状态时,理论上会去自动回收它而不必程序显式调用任何方法。注意我们所说的是“理论上”。也就是说并不能保证一个对象处于“不可达”状态时马上会被垃圾收集线程发现并对其进行回收,虽然Java API中提供了一些触发垃圾回收的方法,如System.gc()等,但是即使我们显式调用了,还是不能保证垃圾回收器被触发工作,这点要特别注意。所以这就会导致一种极端情况出现,如果们的程序中在某个时刻突然出现了大量废弃对象,然而垃圾回收并没有及时对其作相应的处理,很可能造成垃圾对象充满内存,造成“OutOfMemoryError”。

其次,由于回收线程在后台是时事进行的,很可能在没有垃圾的时候做无谓的检查工作(更糟糕的情况就是像上面提到的那样有垃圾时反倒不能及时被触发),造成了时间上的浪费,其检查不可达对象的过程也势必造成了性能耗损。

除了造成时间上的浪费和无谓的性能耗损,垃圾回收器最让人担忧的一个隐患就是,为了保证垃圾回收的顺利进行,Java不得不为已创建的对象加上一些内部信息加以识别。另外,为了将这种回收机制对于每一个对象都同步,还需要一些额外的信息。因此,当JVM开始启动一个程序的时候,对象在内存中比我们实际创建时认为其所占的空间要大得多。下表显示了几种不同类型的Java对象的“内容空间”(也就是该类型的数据所占理论空间)与在JVM中实际空间的对比:

 

User-Accessible

Actual Object Memory Size

JVMs

Types

Contentbytes

JRE 1.1.8

Sun

JRE 1.1.8

IBM

JRE 1.2.2

Classic

JRE 1.2.2

HotSpot

java.lang.Object

0

26

31

28

18

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值