垃圾!
台北市去年开始实施垃圾费随袋征收之后,垃圾量减少了许多,资源回收量也开始大增,大家都说这是个不错的政策。此次春节前,台北市政府为了便民,公布两天开放不收垃圾费(不需专属垃圾袋),结果换来的是一场垃圾清运人员的噩梦。大量的垃圾堆积在各巷道路口,台北市成了垃圾城。
不过这样的场景我可是处变不惊了。究竟我的大学时代四年是在中坜度过,这四年中,中坜市不断地发生垃圾风波,有时候甚至整个桃园地区都浸在酸败腐臭的垃圾堆中,我经常骑车骑一半就要停在路边呕吐一番,然后晕眩着继续上路,到了目的地之后,整个人都虚脱了。经过了这样的大风大浪,你说我怎么会把台北市的这些垃圾放在眼里,更何况台北市的这些垃圾还大都是「新鲜」的,不像当时中坜的垃圾是一两周或一两个月的(写到这里,我打字的手颤抖起来)。
垃圾问题在现实生活中令人头痛,垃圾问题在软件技术圈子同样令人头痛。
自动内存治理也就是俗称的垃圾收集(garbage-collection),可以让程序员减轻许多负担,也减少程序员犯错的机会,所以相当受欢迎。从早期的 Smalltalk,Eiffel,到近期的 Java,C#,Python,REBOL,Ruby... 等,通通支持垃圾收集。垃圾收集差不多已经成了新一代高阶程序语言必备的功能。
在 Java 中,你不需要主动删除对象,而是由 Java 虚拟机器代劳。Java 虚拟机器会「持续追踪」每个对象被使用的情形,假如某对象未被用到,Java 虚拟机器就会自动将其释放。而要如何「持续追踪」,实作细节留给 Java 虚拟机器的实作者发挥。
在早期,许多虚拟机器只是将垃圾收集实作成一个执行绪,一再进行检查,碰到垃圾就释放其内存。因为垃圾收集应该尽量不要影响到原程序的执行,所以虚拟机器将此执行绪的优先权设为 0(最低)。如此一来,当系统有其它执行绪在运作时,就不会进行垃圾收集,所以经常很久才会收集到垃圾,造成内存不足。但又不能因此调高其优先权,否则对 Java 的执行效率是一大打击。所以,我们这些 Java 程序员的计算机 RAM 都要至少 256 MB,否则根本没办法顺利执行 JBuilder 或 VisualAge for Java 等 Java 开发工具,因为这些开发工具本身就是专门吃内存的 Java 程序。我甚至在我的笔记型计算机上装了 512MB 的 RAM。
于是许多人怀念起 C/C++ 来了,他们认为假如 Java 能同时支持自动内存治理和手动内存治理,那么该有多好!他们甚至希望 Java 未来的版本能答应他们主动释放内存,比方说:
MyBigObject obj = new MyBigObject();
// do something here...
delete obj;
假如你也这么希望的话,我劝你早点死了这条心吧!Java 语言的主要精神之一是 robust,假如 Java 同时支持这两种内存治理的话,可能会造成程序中有许多潜在的 Bug,内存不当存取的问题会比 C/C++ 更严重,所以是不可能这么做的。
java.lang.System.gc() 或 java.lang.Runtime.gc() 的 gc 指的就是 garbage-collection,不过根据文件的说明,它的作用只是「建议」Java 虚拟机器快去收垃圾,而不「保证」会去收垃圾。文件都写得如此谦虚了,你也不应该对它寄予太多厚望。对于内存资源消耗太多的缺失,目前你能做的是:
改用一个内存治理方式好一点的虚拟机器:垃圾收集是一个丰富又庞大的主题。垃圾收集的算法有数百种可能,而且各有专长。许多虚拟机器采用的算法都不太一样,建议各位多去比较几家。
少制造垃圾:许多时候你制造了一堆不该制造的垃圾,比方说:该用固定式数组的时候却用 Vector,该用 StringBuffer 的时候却用 String...... 等等。这么会制造垃圾,再多内存也不够用。
不再使用的对象要尽早设定为 null,以便早点被当成垃圾清掉。
花钱多买一些 RAM(砸钱解决问题,这是我最爱用的方式)。
垃圾,真的这么让人讨厌吗?那倒不尽然,我最喜欢的乐团之一就叫做垃圾(Garbage),主唱雪莉曼森(Shirley Manson)的声音真是迷死人了。比起名字很嚣张,但歌声是垃圾的那些偶像,这时候雪莉曼森的垃圾俨然成了一种讽刺。