一:测试WeakHashMap回收对象
下面有转自ITeye的两段代码,来测试WeakHashMap是否真的自动移除其条目,并且如果移除的话在什么时候执行移除:
下面就看看WeakHashMap是如何自动实现移除其内部不用的条目从而达到的自动释放内存的目的的。仔细的看了看JVM自带的源代码的实现,在WeakHashMap是主要通过expungeStaleEntries()这个函数的来实现的。基本上只要对WeakHashMap的内容进行访问就会调用这个函数,从而达到清除其内部不在为外部引用的条目。但是如果预先生成了WeakHashMap,而在GC以前又不曾访问该WeakHashMap,那不是就不能释放内存了吗?
写个代码测试一把:
- public static void main(String[] args) throws Exception {
- List<WeakHashMap<byte[][], byte[][]>> maps = new ArrayList<WeakHashMap<byte[][], byte[][]>>();
- for (int i = 0; i < 1000; i++) {
- WeakHashMap<byte[][], byte[][]> d = new WeakHashMap<byte[][], byte[][]>();
- d.put(new byte[1000][1000], new byte[1000][1000]);
- maps.add(d);
- System.gc();
- System.err.println(i);
- }
- }
由于Java默认内存是64M,所以再不改变内存参数的情况下,该测试跑不了几步循环就内存溢出了,在我配置很低的机器上,跑到243就出错误了“Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at WHMapTest.main(ReflectTest.java:18)”。果不其然,WeakHashMap这个时候并没有自动帮我们释放不用的内存。
再加个对会对map进行访问的测试试试:
- public static void main(String[] args) throws Exception {
- List<WeakHashMap<byte[][], byte[][]>> maps = new ArrayList<WeakHashMap<byte[][], byte[][]>>();
- for (int i = 0; i < 1000; i++) {
- WeakHashMap<byte[][], byte[][]> d = new WeakHashMap<byte[][], byte[][]>();
- d.put(new byte[1000][1000], new byte[1000][1000]);
- maps.add(d);
- System.gc();
- System.err.println(i);
- for (int j = 0; j < i; j++) { //对Map进行访问
- System.err.println(j+ " size" + maps.get(j).size());
- }
- }
- }
这段代码与第一段代码的区别就是添加了一个for循环来对WeakHashMap进行访问,结果就可以顺利执行完,并且打印的所有:“1 size 0 , 2 size 0 ……”,即所有map的大小都是零,执行速度还很快。所以得出结论就是WeakHashMap不是申请了大量的heap空间放在这里不用JVM就自动回收了,而是在访问该Map时,才会把不用的回收掉。
二:OOM错误的注意事项
还有关于报出OOM错误(java.lang.OutOfMemoryError):
使用Java程序从数据库中查询大量的数据时出现异常:java.lang.OutOfMemoryError: Java heap space 在JVM中如果98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。 JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。 例如:java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar 如果Heap Size设置偏小,除了这些异常信息外,还会发现程序的响应速度变慢了。GC占用了更多的时间,而应用分配到的执行时间较少。 Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。 Heap size的 -Xms -Xmn 设置不要超出物理内存的大小。否则会提示“Error occurred during initialization of VM Could not reserve enough space for object heap”。 这个问题的根源是jvm虚拟机的默认Heap大小是64M,可以通过设置其最大和最小值来实现.设置的方法主要是几个. 1.可以在windows 更改系统环境变量加上JAVA_OPTS=-Xms64m -Xmx512m 2,如果用的tomcat,在windows下,可以在C:\tomcat5.5.9\bin\catalina.bat 中加上: set JAVA_OPTS=-Xms64m -Xmx256m 位置在: rem Guess CATALINA_HOME if not defined 这行的下面加合适. 3.如果是linux系统 Linux 在{tomcat_home}/bin/catalina.sh的前面,加 set JAVA_OPTS='-Xms64 -Xmx512'