为了执行某些测试,我想检查当我存储在SoftReference对象缓存中的部分或全部对象被丢弃时我的应用程序的行为。
为了做到这一点,我想手动清除存储在缓存的SoftReference对象中的引用 - 模拟VM处理这些对象 - 但前提是其他任何东西当前都没有对该对象的强引用(可能是最近另一个进程从缓存中检索引用对象的情况。
我的应用程序是单线程的,因此我不需要担心缓存对象的软可达性在执行此代码时会发生变化。这也意味着我目前没有任何锁定机制 - 如果我有的话,我可能已经使用它们来确定一个对象是否被“使用”,因此可以很容易地到达,但是我没有必要这种锁定。
我尝试过的一种方法是为存储在缓存中的每个对象创建一个额外的SoftReference,该对象使用ReferenceQueue注册。我希望在这样做时,缓存中所有可轻松访问的对象都会将其附加的SoftReference添加到队列中,因此我所要做的就是遍历队列,并从缓存中删除这些对象。但是,似乎GC在闲暇时将可轻松访问的对象排入各自的队列,因此无法保证在迭代完缓存中的对象后,任何内容都会添加到队列中。
我还看到的一件事是-XX:SoftRefLRUPolicyMSPerMB JVM选项,其值非常小。通过明智的内存分配,这很可能会在我们可以轻松访问的时候从缓存中清除可轻松访问的对象,但是我真的希望应用程序正常运行,直到我收到清除缓存中可轻松访问的对象的请求。作为JVM选项,我不相信我可以在我的应用程序运行时更改此值。
那么,有没有人对如何确定某个对象是否只能轻柔可达(因此可以被清除)有任何想法?
修改:可能还不清楚的一些额外要点:
答案 0 :(得分:1)
IIRC,保证(在某种意义上)软引用在抛出OutOfMemoryError
之前被清除。因此,如果你分配了大量的内存,如果对象没有被强烈引用,它们应该被清除。 (未经测试。)
答案 1 :(得分:0)
在测试时用替换当前软参考系统的弱参考系统。
弱引用系统会在发生这种情况时立即删除没有其他传入引用的对象,而不是等待jvm运行垃圾回收。
答案 2 :(得分:0)
混合一些答案:正如Tom Hawtin说的那样分配内存直到你出去了,例如用这段代码:
private void doOutOfMemory() {
try {
List<byte[]> list = new ArrayList<byte[]>();
while (true) {
list.add(new byte[200 * 1024 * 1024]);
}
} catch (OutOfMemoryError ex) {
}
}
如果您不想控制清除哪些物体,请对要保留的物体进行强有力的参考。
您也可以使用weakReferences而只调用System.gc()来清除它并不能保证它们将永远被清除......