Java 如何防止对象被垃圾收集?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1329926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent an object from getting garbage collected?
提问by Rahul Garg
How to prevent an object from getting garbage collected?
如何防止对象被垃圾收集?
Are there any approaches by finalize or phantom reference or any other approaches?
是否有通过 finalize 或 phantom reference 或任何其他方法的任何方法?
I was asked this question in an interview. The interviewer suggested that finalize()
can be used.
我在一次采访中被问到这个问题。面试官建议finalize()
可以用。
采纳答案by Tobias
Hold a reference. If your object is getting collected prematurely, it is a symptom that you have a bug in the design of your application.
持有参考。如果您的对象被过早收集,则表明您的应用程序设计存在错误。
The garbage collector collects only objects to which there is no reference in your application. If there is no object that would naturally reference the collected object, ask yourself why it should be kept alive.
垃圾收集器只收集应用程序中没有引用的对象。如果没有对象可以自然地引用收集的对象,那么问问自己为什么要保持它的活动状态。
One usecase in which you typically have no references, but want to keep an object is a singleton. In this case, you could use a static variable. One possible implementation of a singleton would look like this:
一个通常没有引用但想要保留对象的用例是单例。在这种情况下,您可以使用静态变量。单例的一种可能实现如下所示:
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqInstance;
}
}
Edit:Technically, you can store a reference somewhere in your finalizer. This will prevent the object from being collected until the collector determines again that there are no more references. The finalizer will only be called at most once, however, so you must ensure that your object (including its superclasses) need not be finalized after the first collection. I would advise you, however, not to use this technique in actual programs. (It will leave colleagues like me yelling WTF!? ;)
编辑:从技术上讲,您可以在终结器中的某处存储引用。这将阻止对象被收集,直到收集器再次确定没有更多引用。然而,终结器最多只会被调用一次,因此您必须确保您的对象(包括其超类)在第一次收集后不需要被终结。但是,我建议您不要在实际程序中使用这种技术。(它会让像我这样的同事大喊 WTF!?;)
protected void finalize() throws Throwable {
MyObjectStore.getInstance().store(this);
super.finalize(); // questionable, but you should ensure calling it somewhere.
}
回答by Thomas Owens
If there is still a reference to the object, it won't get garbage collected. If there aren't any references to it, you shouldn't care.
如果仍然存在对该对象的引用,则不会对其进行垃圾收集。如果没有对它的任何引用,您就不必在意。
In other words - the garbage collector only collects garbage. Let it do its job.
换句话说 - 垃圾收集器只收集垃圾。让它发挥作用。
回答by Zoidberg
I believe there is a pattern out there for this. Not sure if it the factory pattern. But you have one object that creates all your objects and holds a reference to them. When you are finished with them, you de-reference them in the factory, making the call explicit.
我相信有一个模式可以做到这一点。不知道是不是工厂模式。但是你有一个对象来创建你所有的对象并保存对它们的引用。当您完成它们时,您在工厂中取消对它们的引用,使调用变得明确。
回答by Simon Nickerson
I suspect what you might be referring to is if your finalize
method stashes away a reference to the object being finalized. In this case (if my reading of the Java Language Specis correct) the finalize
method will never be re-run, but the object will not yet be garbage collected.
我怀疑您可能指的是您的finalize
方法是否隐藏了对正在最终确定的对象的引用。在这种情况下(如果我对Java 语言规范的阅读是正确的)该finalize
方法将永远不会重新运行,但该对象还不会被垃圾收集。
This is not the sort of thing one does in real life, except possibly by accident!
这不是人们在现实生活中所做的那种事情,除非可能是偶然的!
回答by Steve B.
This sounds like one of those interview-only-time-you'll-see-it questions. finalize() is run when your object is getting garbage collected, so it'd be pretty perverse to put something in there to prevent collection. Normally you just hold a reference and that's all you need.
这听起来像是那些只在面试时你会看到的问题之一。finalize() 在你的对象被垃圾收集时运行,所以在那里放一些东西来防止收集是非常不正常的。通常你只需要持有一个参考,这就是你所需要的。
I'm not even sure what would happen if you'd create a new reference for something in the finalizer - since the garbage collector's already decided to collect it would you then end up with a null ref? Seems like a poor idea, in any case. e.g.
我什至不确定如果你在终结器中为某些东西创建一个新的引用会发生什么 - 因为垃圾收集器已经决定收集它,你最终会得到一个空引用吗?无论如何,这似乎是一个糟糕的主意。例如
public class Foo {
static Foo reference;
...
finalize (){
reference = this;
}
}
I doubt this would work, or it might work but be dependant on the GC implenetation, or be "unspecified behavior". Looks evil, though.
我怀疑这会起作用,或者它可能起作用但取决于 GC 实现,或者是“未指定的行为”。不过看起来很邪恶。
回答by CPerkins
The trick answer your interviewer was looking for is probably that he wants you to know that you can prevent garbage collection from removing an object by forcing a memory leak.
您的面试官正在寻找的技巧答案可能是他希望您知道您可以通过强制内存泄漏来防止垃圾收集删除对象。
Obviously, if you keep a reference to the object in some long-lived context, it won't be collected, but that's not what the OP's recruiter asked about. That's not something which happens in the finalize method.
显然,如果您在某个长期存在的上下文中保留对对象的引用,它将不会被收集,但这不是 OP 的招聘人员所询问的。这不是在 finalize 方法中发生的事情。
What you can do to prevent garbage collection from within the finalize method is to write an infinite loop, in which you call Thread.yield();
(presumably to keep an empty loop from being optimized away):
为了防止在 finalize 方法中进行垃圾回收,您可以编写一个无限循环,您可以在其中调用Thread.yield();
(大概是为了防止空循环被优化掉):
@Override
protected void finalize() throws Throwable {
while (true) {
Thread.yield();
}
}
My reference here is an article by Elliot Back, in which describes forcing a memory leak by this method.
我在这里参考的是Elliot Back的一篇文章,其中描述了通过这种方法强制内存泄漏。
Just another way in which finalize methods are evil.
finalize 方法是邪恶的另一种方式。
回答by Praveen Kumar Verma
The key point is if we set the real reference variable pointing to the object null,although we have instance variables of that class pointing to that object not set to null. The object is automatically eligible for garbage collection.if save the object to GC, use this code...
关键是如果我们将指向对象的真实引用变量设置为空,尽管我们有指向该对象的类的实例变量未设置为空。该对象自动符合垃圾回收条件。如果将对象保存到 GC,请使用此代码...
public class GcTest {
public int id;
public String name;
private static GcTest gcTest=null;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("In finalize method.");
System.out.println("In finalize :ID :"+this.id);
System.out.println("In finalize :ID :"+this.name);
gcTest=this;
}
public static void main(String[] args) {
GcTest myGcTest=new GcTest();
myGcTest.id=1001;
myGcTest.name="Praveen";
myGcTest=null;
// requesting Garbage Collector to execute.
// internally GC uses Mark and Sweep algorithm to clear heap memory.
// gc() is a native method in RunTime class.
System.gc(); // or Runtime.getRuntime().gc();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\n------- After called GC () ---------\n");
System.out.println("Id :"+gcTest.id);
System.out.println("Name :"+gcTest.name);
}
}
Output :
输出 :
In finalize method.
In finalize :ID :1001
In finalize :ID :Praveen
在finalize方法中。
在敲定中:ID :1001
在敲定中:ID :Praveen
------- After called GC () --------
------- 调用GC()后--------
Id :1001
Name :Praveen
编号 :1001
名称 :Praveen
回答by Ed Handy
I wonder if what they're going for is the pattern with resource pools (e.g. for network/db connections, or threads) where you use finalize to return a resource to the pool so that the actual object holding the resource isn't GC'ed.
我想知道他们想要的是资源池模式(例如用于网络/数据库连接或线程),您使用 finalize 将资源返回到池中,以便实际持有资源的对象不是 GC'编。
Stupid example, in Java-like pseudocode and missing any kind of synchronization:
愚蠢的例子,在类似 Java 的伪代码中并且缺少任何类型的同步:
class SlowResourceInternal {
private final SlowResourcePool parent;
<some instance data>
returnToPool() {
parent.add(this);
}
}
class SlowResourceHolder {
private final SlowResourceInternal impl;
<delegate actual stuff to the internal object>
finalize() {
if (impl != null) impl.returnToPool();
}
}
回答by Satyendra
We have three ways to achieve same - 1) Increasing the Heap -Eden space size . 2) Create Singleton class with Static reference . 3) Override finalize() method and never let that object dereference.
我们有三种方法可以实现相同的目标 - 1) 增加 Heap-Eden 空间大小。2)使用静态引用创建单例类。3) 覆盖 finalize() 方法,永远不要让该对象取消引用。
回答by nandal
There are 3 ways to prevent an Object from Garbage Collection as following:-
有 3 种方法可以防止对象被垃圾收集,如下所示:-
Increase the Heap Size of JVM
// Xms specifies initial memory to be allocated // and Xmx specifies maximum memory can be allocated java -Xms1024m -Xmx4096m ClassFile
Use a SingleTon Class Object as @Tobias mentioned
public class MySingletonClass { private static MySingletonClass uniqueInstance; // marking constructor as private private MySingletonClass() { } public static synchronized MySingletonClass getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqInstance; } }
We can override finalize method. That is last method executed on an object. Hence, it will remain in memory.
// using finalize method class MyClassNotGc{ static MyClassNotGc staticSelfObj; pubic void finalize() { // Putting the reference id //Object reference saved. //The object won't be collected by the garbage collector staticSelfObj = this; } }
增加JVM的堆大小
// Xms specifies initial memory to be allocated // and Xmx specifies maximum memory can be allocated java -Xms1024m -Xmx4096m ClassFile
使用提到的@Tobias 的 SingleTon 类对象
public class MySingletonClass { private static MySingletonClass uniqueInstance; // marking constructor as private private MySingletonClass() { } public static synchronized MySingletonClass getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqInstance; } }
我们可以覆盖 finalize 方法。这是在对象上执行的最后一个方法。因此,它将保留在内存中。
// using finalize method class MyClassNotGc{ static MyClassNotGc staticSelfObj; pubic void finalize() { // Putting the reference id //Object reference saved. //The object won't be collected by the garbage collector staticSelfObj = this; } }