1. 现在我们一起来看一个看起来幼稚但却又很容易被人忽略的程序:
程序要求:创建一个大小为 100 MB 的byte类型的数组:
public class OutOfMemory
{
public static void main(String args[])
{
byte b = new byte[1024*1024*100] ;
}
}
运行会报出如下的错误 : OutOfMemoryError: Java heap space
(实际上是在byte[]的大小不能超过58 MB ,对于 int[] 类型的大小不能超过14 MB ,也就是说不同类型的数组的最大length 的限度也是不同的)
解析:
java.lang.OutOfMemoryError: ( 内存不足)
Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector
( JAVA 虚拟机没有足够的内存分配给对象,垃圾收集器也没有多余的内存可供使用时,将报出 java.lang.OutOfMemoryError , )
呵呵 !看到这或许有人会说谁会犯这么低级的错误啊 ?但是想想你在平时是不是经常用到一些类似这样的语句:
InputStream xmlStream = new FileInputStream("data/workflow1.xml");
byte[] datas = new byte[xmlStream.available()];
呵呵。在看这些程序的时候是不是觉得是那么的眼熟,那么的合理可是细想想是不是有可能和我们上面的程序犯同样的一个错误 ?呵呵 !
不过这样的程序给了我另一个想法 :
思考:
no more memory could be made available by the garbage collector:
(?):也就是说在程序抛出异常之前应该会去调用了System. finalize( )方法,回收一些不再使用的对象吗?呢么我们可以怎么应用 java.lang.OutOfMemoryError ?能不能用OutOfMemoryError来管理对象的生命周期呢 ?
先试试看:JAVA自带的垃圾回收机制,是不是能够及时的进行垃圾回收 ?
例子1:
public class Person
{
public void finalize()
{
System.out.println("The object is going !");
}
/**
* main( ) 中创建了三个 Person( )
*/
public static void main(String[] args)
{
new Person();
new Person();
new Person();
// new Person(); 读者可以将这行的注释符号去掉,再运行试试 ,将有另一个结果!
System.out.println("The program is ending !");
}
}
运行结果:
(?)这是怎么回事啊 ?finalize() 怎么没有被调用啊 ?
原来, JAVA的垃圾回收机制是非常懒惰的,只有在对象向堆所请求的内存不足时,垃圾收集器(Garbage Collector)才会启动,释放那些引用数为零的对象所占用的内存,Java不会自动释放无用的对象的引用。
那么我们修改例子1代码:
import java.lang.Exception;
public class Person
{
public void finalize()
{
System.out.println("The object is going !");
}
public static void main(String[] args)throws Exception
{
new Person();
try
{
int by[] = new int[1024*1024*15];
System.out.println("OK");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
查看运行结果:
看来java.lang.OutOfMemoryErr帮助我们收垃圾了 !(只不过这个收垃圾的工资要求太高了)。
思考:( 想法不一定可行 )
我们可否用 Error 或者 Exception 来控制对象的生命周期呢 ,象OutOfMemoryErr 这样收垃圾的未免有点太高销了,怎么寻找一个低廉的Err 或者 Exception ?