2

为了执行一些测试,我想检查当我存储在 SoftReference 对象缓存中的部分或全部对象被处置时我的应用程序的行为。

为了做到这一点,我想手动清除存储在缓存的 SoftReference 对象中的引用 - 模拟 VM 处理这些对象 - 但前提是当前没有其他任何东西对该对象具有强引用(如果另一个进程最近从缓存中检索了引用的对象)。

我的应用程序是单线程的,所以我不需要担心缓存对象的软可达性会随着代码的执行而改变。这也意味着我目前没有任何锁定机制 - 如果我有,我可能已经使用这些来确定一个对象是否“正在使用”并因此可以强访问,但可惜我不需要这种锁定。

我尝试过的一种方法是为存储在缓存中的每个对象创建一个额外的 SoftReference,该缓存已注册到 ReferenceQueue。我希望这样做时,缓存中的所有软可访问对象都会将它们的附加 SoftReference 添加到队列中,所以我所要做的就是遍历队列,并从缓存中删除这些对象。但是,似乎 GC 在闲暇时会将可轻松访问的对象排入其各自的队列,因此一旦我完成对缓存中的对象的迭代,就不能保证任何东西都会添加到队列中。

我还看过的一件事是 -XX:SoftRefLRUPolicyMSPerMB JVM 选项,它的值非常小。通过明智的内存分配,这很可能会在软可访问的那一刻为我从缓存中清除软可访问的对象,但我真的希望应用程序正常运行,直到我收到从缓存中清除软可访问对象的请求. 作为 JVM 选项,我不相信我可以在我的应用程序运行时更改此值。

那么,是否有人对我如何确定一个对象是否只能轻触(因此可以清除)有任何想法?

编辑:可能还不清楚的一些额外点:

  • 当我想清除这些软引用对象时,该应用程序可能会做有用​​的工作。所以我宁愿不要尝试让 GC 为我清除对象。
  • 如果我可以选择清除哪些可轻松到达的对象,那将是更可取的。
  • 我想让应用程序正常运行,即使用生产内存设置。更改代码中的设置,然后可以将其重置回其生产值,这很好。
4

3 回答 3

1

IIRC,保证(在某种意义上)在OutOfMemoryError抛出之前清除软引用。因此,如果您分配大量内存,如果对象没有被强引用,它们应该被清除。(未测试。)

于 2009-05-15T11:46:15.417 回答
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() 来清除,不能保证它们总是会被清除...

于 2009-05-15T14:13:01.087 回答
0

在测试时用弱参考系统代替您当前的软参考系统。

一旦发生这种情况,弱引用系统将立即删除没有其他传入引用的对象,而不是等待 jvm 运行垃圾收集。

于 2009-05-15T12:03:56.560 回答