我已经阅读了关于这个主题的这篇文章,但我真的不明白它.在描述概念时,请给我一些建议和示例.
java reference weak-references phantom-reference soft-references
有人可以解释三个参考类之间的区别(或发布链接到一个很好的解释)?SoftReference
> WeakReference
> PhantomReference
,但当我会用每一个?为什么会出现WeakHashMap
,但没有SoftHashMap
或PhantomHashMap
?
如果我使用以下代码......
WeakReference<String> ref = new WeakReference<String>("Hello!");
if (ref != null) { // ref can get collected at any time...
System.gc(); // Let's assume ref gets collected here.
System.out.println(ref.get()); // Now what?!
}
Run Code Online (Sandbox Code Playgroud)
...怎么了?我是否必须ref
在每个语句之前检查是否为null(这是错误的,但我应该怎么做)?对不起快速问题,但我无法理解这些Reference
课程......谢谢!
java reference weak-references phantom-reference soft-references
可能重复:
你有没有在任何项目中使用Phantom参考?
我已经阅读了不同类型的参考资料.我理解强大,软弱的参考是如何运作的.
但是,当我读到幻影参考时,我无法理解它们.也许是因为我找不到任何好的例子来告诉我他们的目的是什么或何时使用它们.
你能告诉我一些使用幻像参考的代码示例吗?
幻影参考用于验尸操作.Java规范规定,在清除幻像引用本身之前,不会释放幻像引用的对象.
我的问题是:此功能(对象未解除分配)的用途是什么?
(我提出的唯一想法是允许本机代码对对象进行事后清理,但这并不是很有说服力).
我阅读了很多文章,但我不明白 - 在实践中我需要在哪里使用Weak和Phantom参考?软错误引用 - 正如我所理解的那样,是缓存的不错选择.但弱和幻影,我不知道何时使用.请提供我们需要使用它们的实际任务的示例.
我正在尝试实现一种机制,当持有它们的对象死亡时删除缓存的文件,并决定使用PhantomReference
s来获取有关对象的垃圾收集的通知.问题是我一直在经历着奇怪的行为ReferenceQueue
.当我在代码中更改某些内容时,它突然不再获取对象.所以我试着让这个例子进行测试,并遇到了同样的问题:
public class DeathNotificationObject {
private static ReferenceQueue<DeathNotificationObject>
refQueue = new ReferenceQueue<DeathNotificationObject>();
static {
Thread deathThread = new Thread("Death notification") {
@Override
public void run() {
try {
while (true) {
refQueue.remove();
System.out.println("I'm dying!");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
};
deathThread.setDaemon(true);
deathThread.start();
}
public DeathNotificationObject() {
System.out.println("I'm born.");
new PhantomReference<DeathNotificationObject>(this, refQueue);
}
public static void main(String[] args) {
for (int i = 0 ; i < 10 ; i++) {
new DeathNotificationObject(); …
Run Code Online (Sandbox Code Playgroud) 适用于PhantomReference的 Javadoc 8 指出:
与Java终结机制相比,虚拟引用最常用于以更灵活的方式调度事前清理操作。
因此,我尝试创建一个线程,该线程正在调用close()
符合垃圾回收条件的Test Object方法。在run()
试图获得所有测试对象的预验。
实际上,检索到的测试对象都是null
。预期的行为是检索测试对象并调用该close
方法。
无论创建多少个测试对象,都不会在验尸前捕获单个测试对象(您必须增加超时并多次调用GC)。
我究竟做错了什么?这是Java错误吗?
我试图创建一个最小,完整和可验证的示例,但是它仍然很长。我java version "1.8.0_121"
在Windows 7 64位上使用32位。
public class TestPhantomReference {
public static void main(String[] args) throws InterruptedException {
// Create AutoClose Thread and start it
AutoCloseThread thread = new AutoCloseThread();
thread.start();
// Add 10 Test Objects to the AutoClose Thread
// Test Objects are directly eligible for GC
for (int i …
Run Code Online (Sandbox Code Playgroud) java garbage-collection phantom-reference finalize finalizer
正如Google I/O '17中的Hans Boehm所说的" 如何在Android中管理本机C++内存 "建议我使用PhantomReference
该类来确保正确删除本地对等体.
在18分57秒的链接视频中,他展示了一个对象的示例实现,该对象将其自身注册到PhantomReference
类的类型.这PhantomReference
节课,他以19分49秒的成绩表演.所以我为我的示例对象复制了他的方法.见下文.
虽然这种方法很好,但它不能扩展.我将需要创建相当多的对象,我还没有找到一种方法来创建一个基类(对于我的对象或PhantomReference
基类),它将接受任何对象,并将正确处理本机删除.
如何创建一个PhantomReference
可以在提供的对象上调用本机静态方法的通用基类?
我试图转换PhantomReference
泛型,但本机静态删除方法阻碍了实现.
我的 WorkViewModel
import android.databinding.*;
public class WorkViewModel extends BaseObservable
{
private long _nativeHandle;
public WorkViewModel(Database database, int workId)
{
_nativeHandle = create(database.getNativeHandle(), workId);
WorkViewModelPhantomReference.register(this, _nativeHandle);
}
private static native long create(long databaseHandle, int workId);
static native void delete(long nativeHandle);
@Bindable
public native int getWorkId();
public native void setWorkId(int workId);
}
Run Code Online (Sandbox Code Playgroud)
我的 WorkViewModelPhantomReference
import …
Run Code Online (Sandbox Code Playgroud) 我有PR,PR指向的对象O,以及为PR设置的RQ.我有一个线程继续轮询RQ,并在它在RQ中找到的第一个引用,线程打印它找到它的时间,然后退出.
事情很好,但是当O有一个finalize(无论多么微不足道)的时候,线程不再在RQ中找到引用并且无限期地继续运行.
问题:为什么会这样?我正在使用Sun JDK 1.6.
这是代码:
good case
public class MyGCPhantom
{
public static void main(String[] args) throws InterruptedException
{
GCPhantomObject p = new GCPhantomObject();
ReferenceQueue phantomQueue = new ReferenceQueue();
PhantomReference<GCPhantomObject> pr = new PhantomReference<GCPhantomObject>(p, phantomQueue);
new GCPhantomThread(phantomQueue, "Phantom").start();
p = null;
System.gc();
}
}
class GCPhantomObject
{
@Override
protected void finalize()
{
//System.out.println("GCPhantom finalized " + System.currentTimeMillis());
}
}
class GCPhantomThread extends Thread
{
private ReferenceQueue referenceQueue;
private String name;
GCPhantomThread(ReferenceQueue referenceQueue, String name)
{
this.referenceQueue = referenceQueue;
this.name …
Run Code Online (Sandbox Code Playgroud) 根据链接https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html,只有当对象从内存中物理移除并且WeakReferences在最终化或垃圾收集之前排队时才会加入PhantomReferences实际发生了.
区别在于排队发生的时间.WeakReferences在它们指向的对象变得无法访问时立即排队.这是在最终确定或垃圾收集实际发生之前; 理论上,对象甚至可以通过非正统的finalize()方法"复活",但WeakReference仍然会死亡.只有在从内存中物理移除对象时,才会将PhantomReferences排队,并且get()方法始终返回null,以防止您"复活"几乎死亡的对象.
而根据http://www.ibm.com/developerworks/library/j-refs/,在释放堆对象之前将PhantomReference添加到其ReferenceQueue中,并在完成或垃圾回收后将WeakReferences添加到其ReferenceQueue.
与软引用和弱引用不同,PhantomReference在释放堆对象之前会添加到其ReferenceQueue中.(请记住,必须使用关联的ReferenceQueue创建所有PhantomReference对象.)这允许在回收堆对象之前采取操作.
当运行堆对象的finalize()方法并释放其内存时,WeakReference对象将添加到其ReferenceQueue(如果存在).
我很迷惑.哪一个是正确的?
基本上我想知道关于Reference Queue的弱引用和幻像引用之间的区别?
java garbage-collection weak-references phantom-reference soft-references