考虑一个使用 PhantomReferences 的库来避免终结器,同时确保一些 JNI 资源被释放。
一种体系结构涉及参考队列和在参考队列上执行清理的线程阻塞。
现在来了一个问题:如何对所有这些进行测试?
- 设置系统
- 创建感兴趣的对象
- 让它变成垃圾
- 系统.gc()
- 不知何故等待线程醒来,闻咖啡,然后完成工作
- 断言内部计数器被勾选以证明所有这些都发生了
Thread.sleep()
对第5 项有效但令人不安。Thread.yield()
根本不可靠。如果有的话,还有哪些其他选择?
考虑一个使用 PhantomReferences 的库来避免终结器,同时确保一些 JNI 资源被释放。
一种体系结构涉及参考队列和在参考队列上执行清理的线程阻塞。
现在来了一个问题:如何对所有这些进行测试?
Thread.sleep()
对第5 项有效但令人不安。Thread.yield()
根本不可靠。如果有的话,还有哪些其他选择?
假设您正在使用小于 2GB 的堆运行,分配一个刚好小于可用堆大小的字节数组应该会在抛出预期的 OutOfMemoryError 之前立即触发一个完整的 gc:
byte[] foo = new byte[(int) (Runtime.getRuntime().maxMemory()-1)];
我不会使字节数组大于堆大小,因为在这种情况下,VM 可能会立即抛出 OutOfMemoryError,因为它知道它无论如何都无法提供那么多堆。
如果您可以对相关库进行更改,则将一个可选参数传递BlockingQueue<Reference?>>
给清理代码,以便它可以发出完成信号。如果队列存在,则清理代码在执行清理后将对队列的引用入队。测试代码可以调用BlockingQueue.poll(timeout)
——清理完成后立即接收引用,或者如果清理没有在您确定的某个合理的上限超时时间内完成,则超时。