S
Scott W Gifford
Hello,
I'm experimenting with the SoftReference class, for possible use in
implementing a cache. I'm finding, however, that if the class I'm
holding a SoftReference to has a finalize() method, then I run out of
memory even if there are still SoftReference objects that should be
garbage-collectable.
Here's a small example:
import java.util.*;
import java.lang.ref.*;
public class SoftRef {
final static int NUM_BLOCKS = 256;
final static int BLOCK_SIZE = 1000000;
private final static class MemoryHog {
byte[] arr;
public MemoryHog(int size) {
arr = new byte[size];
Arrays.fill(arr,(byte) 3);
}
public void finalize() {
System.out.println("Finalizing " + this);
}
}
public static int liveCount(List<? extends Reference<?>> list) {
int count = 0;
for(Reference<?> e: list) {
if (e.get() != null)
count++;
}
return count;
}
public static void main(String[] args) {
ArrayList<SoftReference<MemoryHog>> hogPen = new ArrayList<SoftReference<MemoryHog>>(NUM_BLOCKS);
for(int i=1;i<=NUM_BLOCKS;i++) {
hogPen.add(new SoftReference<MemoryHog>(new MemoryHog(BLOCK_SIZE)));
System.out.println("Allocated " + i + " blocks; " + liveCount(hogPen) + " still alive.");
}
}
}
When I run this, I get:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
However, if I remove the finalize() method from the MemoryHog class,
it works fine.
If I aggressively run System.gc() during the runs, I don't run out of
memory, which leads me to believe that I'm not holding any extra
hard-references preventing these objects from being collected.
I thought maybe the garbage collection thread couldn't keep up with
running all of these finalizers, so I tried adding a Thread.sleep(100)
inside the loop, and that didn't help. Calling System.gc() then
System.runFinalization() once in each loop didn't help, either; I had
to call them multiple times.
Anybody know what's going on here, and how to prevent it? I'm using
Sun's Java 1.5.0_06 (I also tried 1.5.0_01).
Thanks!
----ScottG.
I'm experimenting with the SoftReference class, for possible use in
implementing a cache. I'm finding, however, that if the class I'm
holding a SoftReference to has a finalize() method, then I run out of
memory even if there are still SoftReference objects that should be
garbage-collectable.
Here's a small example:
import java.util.*;
import java.lang.ref.*;
public class SoftRef {
final static int NUM_BLOCKS = 256;
final static int BLOCK_SIZE = 1000000;
private final static class MemoryHog {
byte[] arr;
public MemoryHog(int size) {
arr = new byte[size];
Arrays.fill(arr,(byte) 3);
}
public void finalize() {
System.out.println("Finalizing " + this);
}
}
public static int liveCount(List<? extends Reference<?>> list) {
int count = 0;
for(Reference<?> e: list) {
if (e.get() != null)
count++;
}
return count;
}
public static void main(String[] args) {
ArrayList<SoftReference<MemoryHog>> hogPen = new ArrayList<SoftReference<MemoryHog>>(NUM_BLOCKS);
for(int i=1;i<=NUM_BLOCKS;i++) {
hogPen.add(new SoftReference<MemoryHog>(new MemoryHog(BLOCK_SIZE)));
System.out.println("Allocated " + i + " blocks; " + liveCount(hogPen) + " still alive.");
}
}
}
When I run this, I get:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
However, if I remove the finalize() method from the MemoryHog class,
it works fine.
If I aggressively run System.gc() during the runs, I don't run out of
memory, which leads me to believe that I'm not holding any extra
hard-references preventing these objects from being collected.
I thought maybe the garbage collection thread couldn't keep up with
running all of these finalizers, so I tried adding a Thread.sleep(100)
inside the loop, and that didn't help. Calling System.gc() then
System.runFinalization() once in each loop didn't help, either; I had
to call them multiple times.
Anybody know what's going on here, and how to prevent it? I'm using
Sun's Java 1.5.0_06 (I also tried 1.5.0_01).
Thanks!
----ScottG.