referent
在java语言中是什么意思?
我phantom references
在 java 中阅读时遇到了这个词,但在那里没有解释,只是使用了(这个词)。我也无法通过谷歌搜索找到答案。
我可以从上下文中得出结论,它是引用指向的对象,但不确定所以我想确定它是什么。
编辑:正如评论中所建议的,我正在添加一个使用该词的上下文:
垃圾收集器在执行其所指对象的 finalize 方法后,将幻像引用添加到引用队列中。这意味着该实例仍在内存中。
API文档说
此引用类型与其他引用类型的不同之处在于它不用于访问对象,而是作为对象已经完成的信号,并且垃圾收集器已准备好回收其内存.
如果Phantom引用不能用于访问对象,那么垃圾收集器如何回收此对象使用的内存?
在C++中,我使用引用计数对象来填充"自动"回收对象池
SmartPointer<ObjType> object = pool.getObject(); // hold reference
// ... do stuff with object over time.
object = nullptr; // that is when reference
// count goes to 0
Run Code Online (Sandbox Code Playgroud)
- 现在我在C++对象上有一个"onFinalRelease()"方法,当refcount达到0时会被调用.我可以覆盖它(默认是delete(this))来自动回收对象而不是销毁它们.
问题是我可以使用java引用类型和引用池的某种组合来实现此模式.当然,这对于一种大型复杂的昂贵而言,在有意义的情况下创建对象.那是我想做的:
SomeReference r = referenceQueue.getReference();
pool.recycle(r.takeBackUnusedObjectFromGC()); // ??????????????????????????
Run Code Online (Sandbox Code Playgroud)
这真是太棒了:)
java garbage-collection weak-references phantom-reference soft-references
Java允许编写:
new PhantomReference(new Object(), null)
Run Code Online (Sandbox Code Playgroud)
在这种情况下new Object()
将被收集?
据我了解,幻影引用是finalize()
方法使用的替代方法。
在队列中出现引用后,我需要执行一些其他操作,然后运行 clear()
Java Doc保留:
可以使用空队列创建幻影引用,但是这种引用完全没有用:其get方法将始终返回null,并且由于它没有队列,因此永远不会入队。
如果它永远不会被排队,那意味着什么?
据我了解,这意味着在完成方法调用后,引用不会再添加到referenceQueue中。因此可能导致:
1.对象存储器将立即被清除
2.对象存储器将不会被清除
哪种情况正确?
我一直在阅读有关PhantomReference https://www.baeldung.com/java-phantom-reference的文章,并在此处找到了简化的示例代码:
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
Object object = new Object();
PhantomReference<Object> phantomReference = new PhantomReference<>(object, referenceQueue);
object = null;
System.gc();
Thread.sleep(1_000);
System.out.println("isEnqueued() after GC: " + phantomReference.isEnqueued());
Reference reference = referenceQueue.poll();
if(reference != null) {
System.out.println("isEnqueued() after poll(): " + phantomReference.isEnqueued());
}
}
Run Code Online (Sandbox Code Playgroud)
输出如下:
isEnqueued() after GC: true
isEnqueued() after poll(): false
Run Code Online (Sandbox Code Playgroud)
因此,一切工作都按预期进行,将对对象的强引用设置为null(GC会将其检测到)并将幻像引用添加到队列中。
现在在那篇文章中,他们说:“垃圾收集器在执行其引用的finalize方法之后,将一个幻像引用添加到引用队列。这意味着该实例仍在内存中。”
所以我想进行测试并覆盖finalize方法,例如:
Object object = new Object() {
@Override
protected void finalize() throws Throwable {
System.out.println("finalize()"); …
Run Code Online (Sandbox Code Playgroud) PhantomReference
java 8及以下版本的java doc如下所示:
Phantom 引用对象,在收集器确定它们的引用对象可能会被回收后入队。幻像引用最常用于以比 Java 终结机制更灵活的方式调度预检清理操作。如果垃圾收集器在某个时间点确定幻像引用的所指对象是幻像可达的,那么在那个时候或稍后的某个时间它将将该引用加入队列。
为了确保可回收对象保持如此,可能无法检索幻像引用的所指对象:幻像引用的 get 方法始终返回 null。
与软引用和弱引用不同,幻像引用在入队时不会被垃圾收集器自动清除。可通过幻像引用访问的对象将保持不变,直到所有此类引用都被清除或自身变得无法访问
PhantomReference
java 9及更高版本的java doc如下所示:
Phantom 引用对象,在收集器确定它们的引用对象可能会被回收后入队。虚拟引用最常用于安排事后清理操作。假设垃圾收集器在某个时间点确定某个对象是虚拟可达的。届时,它将自动清除对该对象的所有幻影引用以及对该对象可从中访问的任何其他幻影可访问对象的所有幻影引用。同时或稍后它会将那些注册到引用队列的新清除的幻像引用加入队列。
为了确保可回收对象保持如此,可能无法检索幻像引用的所指对象:幻像引用的 get 方法始终返回 null。
java 9中的PhantomReference行为是否发生了变化?还是只是 Java 创始人重新思考了该课程的奉献精神?
嗨我对幻像参考有一个疑问.我理解的是,在对象进行垃圾收集之前调用finalize方法.但是有时候如果对象不符合垃圾回收的条件,那么finalize方法将不会执行.
现在讨论调用此finalize方法时的幻像引用.
是否总是在幻像参考中调用finalize.
我对此非常困惑.请帮我.
我正在使用 Mysql GET_LOCK在分布式系统中实现锁定服务。在调用我的 getLock() 方法时,如果客户端获得了锁,我会在数据库中创建一个条目并在释放锁时删除该条目。
假设调用客户端将在达到其目的后释放锁。但是,我想确保在客户端不释放它或不进行适当清理的情况下释放锁。
一种方法是在我的锁定对象上使用 finalize 方法以在调用 finalize 时释放它。然而,它并不理想,增加了复杂性并且在 Java 9 中被弃用。我读到了比终结器更好的 Phantom 引用,但它的复杂程度也很高。我把它作为我的最后手段。
有没有更简单、更少依赖 JVM 的方法来处理这个用例?
java garbage-collection phantom-reference finalize finalizer
我试着理解课堂 ReferenceQueue
它是可选的构造函数参数
SoftReference
Run Code Online (Sandbox Code Playgroud)
和
WeakReference
Run Code Online (Sandbox Code Playgroud)
它也是 的强制性参数PhantomReference
。
根据我读过的信息,我可以写一些论文
a) 对于 PhantomReference 方法 get 总是返回 null
b)
对于 Phantom 引用:
1. gc 检测到该对象可以从内存中删除
2. 对放入 ReferenceQueue 的对象的引用,
当我们调用 clear 或 link to reference from queue 时无法访问并且 gc 看到 3. finalize 方法调用
4.
为弱/软引用释放内存:
1. gc 检测到该对象可以从内存中删除
2. 终结方法调用
3. 释放内存
4. 对放入队列的对象的引用
XXXReference
构造函数?PhantomReference
没有没有构造函数ReferenceQueue
?我一直在讨论与前一个问题相关的成员函数指针.在下面的代码中,我调用类(B)上的方法来更改其中的变量(count),但我从不创建此类的实例.为什么这样做?
#include <iostream>
#include <string>
#include <map>
class A;
typedef int (A::*MEMFUNC)(int, int);
#define HANDLER(aclass, aproc) (MEMFUNC)(&aclass::aproc)
enum
{
ADD=1,
MUL,
SUB,
DIV
};
class B
{
int count;
public:
B() : count(0) {}
~B() {}
int multiply(int x, int y) { count++; return x*y*count; }
int divide(int x, int y) { count++; if (y!=0) return (x/y)*count; else return 0; }
};
class A
{
std::map< int, MEMFUNC > funcs;
public:
A() { AddLocals(); }
~A() {}
int …
Run Code Online (Sandbox Code Playgroud)