如何在java中销毁一个对象?

时间:2022-03-09 04:14:00

I encountered this question in an interview with following options:

我在接受以下选项的采访中遇到了这个问题:

How to destroy an object in java?

如何破坏java中的对象?

a. System.gc();  
b. Runtime.getRuntime.gc();  
c. object.delete();  
d. object.finalize();  
e. Java performs gc by itself, no need to do it manually.
  1. The answer should be e?

    答案应该是e?

  2. what if e was not there? then ? clearly c is not the answer. a and b will do gc for the whole application(question requires for one object). I think it is d because finalize() is called just prior to gc(but is it necessary that after finalize gc is invoked ?) or I am wrong ? e must be there to answer this question ?

    如果e不存在怎么办?然后 ?显然c不是答案。 a和b将为整个应用程序执行gc(问题需要一个对象)。我认为这是因为在gc之前调用finalize()(但是在调用最终化gc之后是否有必要?)或者我错了?我必须在那里回答这个问题吗?

6 个解决方案

#1


49  

Answer E is correct answer. If E is not there, you will soon run out of memory (or) No correct answer.

答案E是正确答案。如果E不存在,您很快就会耗尽内存(或)无正确答案。

Object should be unreachable to be eligible for GC. JVM will do multiple scans and moving objects from one generation to another generation to determine the eligibility of GC and frees the memory when the objects are not reachable.

无法访问对象以符合GC的条件。 JVM将执行多次扫描并将对象从一代移动到另一代,以确定GC的合格性,并在无法访问对象时释放内存。

#2


23  

To clarify why the other answers can not work:

澄清为什么其他答案不起作用:

  1. System.gc() (along with Runtime.getRuntime().gc(), which does the exact same thing) hints that you want stuff destroyed. Vaguely. The JVM is free to ignore requests to run a GC cycle, if it doesn't see the need for one. Plus, unless you've nulled out all reachable references to the object, GC won't touch it anyway. So A and B are both disqualified.

    System.gc()(以及Runtime.getRuntime()。gc(),它完成同样的事情)提示您希望销毁的东西。依稀。如果JVM没有看到需要,那么JVM可以*地忽略运行GC循环的请求。另外,除非您已经清除了对象的所有可访问引用,否则GC无论如何都不会触及它。所以A和B都被取消资格。

  2. Runtime.getRuntime.gc() is bad grammar. getRuntime is a function, not a variable; you need parentheses after it to call it. So B is double-disqualified.

    Runtime.getRuntime.gc()是错误的语法。 getRuntime是一个函数,而不是一个变量;你需要括号来调用它。因此B被双重取消资格。

  3. Object has no delete method. So C is disqualified.

    对象没有删除方法。所以C被取消资格。

  4. While Object does have a finalize method, it doesn't destroy anything. Only the garbage collector can actually delete an object. (And in many cases, they technically don't even bother to do that; they just don't copy it when they do the others, so it gets left behind.) All finalize does is give an object a chance to clean up before the JVM discards it. What's more, you should never ever be calling finalize directly. (As finalize is protected, the JVM won't let you call it on an arbitrary object anyway.) So D is disqualified.

    虽然Object确实有一个finalize方法,但它不会破坏任何东西。只有垃圾收集器才能实际删除对象。 (在许多情况下,他们在技术上甚至不愿意这样做;他们只是在他们做其他人时不复制它,所以它被抛在了后面。)所有最终确定的是给对象一个机会清理之前JVM丢弃它。更重要的是,你永远不应该直接调用finalize。 (由于finalize受到保护,JVM不会让你在任意对象上调用它。)所以D被取消资格。

  5. Besides all that, object.doAnythingAtAllEvenCommitSuicide() requires that running code have a reference to object. That alone makes it "alive" and thus ineligible for garbage collection. So C and D are double-disqualified.

    除此之外,object.doAnythingAtAllEvenCommitSuicide()要求运行代码具有对象的引用。仅这一点使它“活着”,因此没有资格进行垃圾收集。因此C和D被双重取消资格。

#3


14  

Short Answer - E

Answer isE given that the rest are plainly wrong, but ..

答案是因为其余的都是明显错误的,但是......

Long Answer - It isn't that simple; it depends ...

Simple fact is, the garbage collector may never decide to garbage collection every single object that is a viable candidate for collection, not unless memory pressure is extremely high. And then there is the fact that Java is just as susceptible to memory leaks as any other language, they are just harder to cause, and thus harder to find when you do cause them!

简单的事实是,垃圾收集器可能永远不会决定对每个对象进行垃圾收集,这是一个可行的收集候选对象,除非内存压力非常高。然而事实上,Java与任何其他语言一样容易受到内存泄漏的影响,它们更难以引起,因此当您确实导致它们时更难找到它们!

The following article has many good details on how memory management works and doesn't work and what gets take up by what. How generational Garbage Collectors work and Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )

以下文章有许多关于内存管理如何工作和不起作用的详细信息,以及由什么引起的内容。分代垃圾收集器如何工作并感谢内存(了解JVM如何在Windows和Linux上使用本机内存)

If you read the links, I think you will get the idea that memory management in Java isn't as simple as a multiple choice question.

如果您阅读了这些链接,我想您会发现Java中的内存管理并不像多项选择问题那么简单。

#4


6  

Set to null. Then there are no references anymore and the object will become elligable for Garbage Collection. GC will automatically remove the Object from the heap.

设为null。然后就没有引用了,对象将变为可以为垃圾收集设置。 GC将自动从堆中删除Object。

#5


3  

Here is the code:

这是代码:

public static void main(String argso[]) {
int big_array[] = new int[100000];

// Do some computations with big_array and get a result. 
int result = compute(big_array);

// We no longer need big_array. It will get garbage collected when there
// are no more references to it. Since big_array is a local variable,
// it refers to the array until this method returns. But this method
// doesn't return. So we've got to explicitly get rid of the reference
// ourselves, so the garbage collector knows it can reclaim the array. 
big_array = null;

// Loop forever, handling the user's input
for(;;) handle_input(result);
}

#6


0  

In java there is no explicit way doing garbage collection. The JVM itself runs some threads in the background checking for the objects that are not having any references which means all the ways through which we access the object are lost. On the other hand an object is also eligible for garbage collection if it runs out of scope that is the program in which we created the object is terminated or ended. Coming to your question the method finalize is same as the destructor in C++. The finalize method is actually called just before the moment of clearing the object memory by the JVM. It is up to you to define the finalize method or not in your program. However if the garbage collection of the object is done after the program is terminated then the JVM will not invoke the finalize method which you defined in your program. You might ask what is the use of finalize method? For instance let us consider that you created an object which requires some stream to external file and you explicitly defined a finalize method to this object which checks wether the stream opened to the file or not and if not it closes the stream. Suppose, after writing several lines of code you lost the reference to the object. Then it is eligible for garbage collection. When the JVM is about to free the space of your object the JVM just checks have you defined the finalize method or not and invokes the method so there is no risk of the opened stream. finalize method make the program risk free and more robust.

在java中,没有明确的方法来进行垃圾收集。 JVM本身在后台运行一些线程,检查没有任何引用的对象,这意味着我们访问对象的所有方式都将丢失。另一方面,如果对象超出了我们创建对象的程序终止或结束的范围,则该对象也有资格进行垃圾收集。回到你的问题,方法finalize与C ++中的析构函数相同。 finalize方法实际上是在JVM清除对象内存之前调用的。您可以在程序中定义finalize方法。但是,如果在程序终止后完成对象的垃圾收集,则JVM将不会调用您在程序中定义的finalize方法。您可能会问到finalize方法有什么用?例如,让我们考虑您创建了一个对象,该对象需要一些流到外部文件,并且您明确地为此对象定义了一个finalize方法,该方法检查打开到该文件的流是否打开,如果没有则关闭流。假设在编写了几行代码后,您丢失了对该对象的引用。然后它有资格进行垃圾收集。当JVM即将释放对象的空间时,JVM只会检查您是否定义了finalize方法并调用该方法,因此不存在打开的流的风险。 finalize方法使程序无风险且更加健壮。

#1


49  

Answer E is correct answer. If E is not there, you will soon run out of memory (or) No correct answer.

答案E是正确答案。如果E不存在,您很快就会耗尽内存(或)无正确答案。

Object should be unreachable to be eligible for GC. JVM will do multiple scans and moving objects from one generation to another generation to determine the eligibility of GC and frees the memory when the objects are not reachable.

无法访问对象以符合GC的条件。 JVM将执行多次扫描并将对象从一代移动到另一代,以确定GC的合格性,并在无法访问对象时释放内存。

#2


23  

To clarify why the other answers can not work:

澄清为什么其他答案不起作用:

  1. System.gc() (along with Runtime.getRuntime().gc(), which does the exact same thing) hints that you want stuff destroyed. Vaguely. The JVM is free to ignore requests to run a GC cycle, if it doesn't see the need for one. Plus, unless you've nulled out all reachable references to the object, GC won't touch it anyway. So A and B are both disqualified.

    System.gc()(以及Runtime.getRuntime()。gc(),它完成同样的事情)提示您希望销毁的东西。依稀。如果JVM没有看到需要,那么JVM可以*地忽略运行GC循环的请求。另外,除非您已经清除了对象的所有可访问引用,否则GC无论如何都不会触及它。所以A和B都被取消资格。

  2. Runtime.getRuntime.gc() is bad grammar. getRuntime is a function, not a variable; you need parentheses after it to call it. So B is double-disqualified.

    Runtime.getRuntime.gc()是错误的语法。 getRuntime是一个函数,而不是一个变量;你需要括号来调用它。因此B被双重取消资格。

  3. Object has no delete method. So C is disqualified.

    对象没有删除方法。所以C被取消资格。

  4. While Object does have a finalize method, it doesn't destroy anything. Only the garbage collector can actually delete an object. (And in many cases, they technically don't even bother to do that; they just don't copy it when they do the others, so it gets left behind.) All finalize does is give an object a chance to clean up before the JVM discards it. What's more, you should never ever be calling finalize directly. (As finalize is protected, the JVM won't let you call it on an arbitrary object anyway.) So D is disqualified.

    虽然Object确实有一个finalize方法,但它不会破坏任何东西。只有垃圾收集器才能实际删除对象。 (在许多情况下,他们在技术上甚至不愿意这样做;他们只是在他们做其他人时不复制它,所以它被抛在了后面。)所有最终确定的是给对象一个机会清理之前JVM丢弃它。更重要的是,你永远不应该直接调用finalize。 (由于finalize受到保护,JVM不会让你在任意对象上调用它。)所以D被取消资格。

  5. Besides all that, object.doAnythingAtAllEvenCommitSuicide() requires that running code have a reference to object. That alone makes it "alive" and thus ineligible for garbage collection. So C and D are double-disqualified.

    除此之外,object.doAnythingAtAllEvenCommitSuicide()要求运行代码具有对象的引用。仅这一点使它“活着”,因此没有资格进行垃圾收集。因此C和D被双重取消资格。

#3


14  

Short Answer - E

Answer isE given that the rest are plainly wrong, but ..

答案是因为其余的都是明显错误的,但是......

Long Answer - It isn't that simple; it depends ...

Simple fact is, the garbage collector may never decide to garbage collection every single object that is a viable candidate for collection, not unless memory pressure is extremely high. And then there is the fact that Java is just as susceptible to memory leaks as any other language, they are just harder to cause, and thus harder to find when you do cause them!

简单的事实是,垃圾收集器可能永远不会决定对每个对象进行垃圾收集,这是一个可行的收集候选对象,除非内存压力非常高。然而事实上,Java与任何其他语言一样容易受到内存泄漏的影响,它们更难以引起,因此当您确实导致它们时更难找到它们!

The following article has many good details on how memory management works and doesn't work and what gets take up by what. How generational Garbage Collectors work and Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )

以下文章有许多关于内存管理如何工作和不起作用的详细信息,以及由什么引起的内容。分代垃圾收集器如何工作并感谢内存(了解JVM如何在Windows和Linux上使用本机内存)

If you read the links, I think you will get the idea that memory management in Java isn't as simple as a multiple choice question.

如果您阅读了这些链接,我想您会发现Java中的内存管理并不像多项选择问题那么简单。

#4


6  

Set to null. Then there are no references anymore and the object will become elligable for Garbage Collection. GC will automatically remove the Object from the heap.

设为null。然后就没有引用了,对象将变为可以为垃圾收集设置。 GC将自动从堆中删除Object。

#5


3  

Here is the code:

这是代码:

public static void main(String argso[]) {
int big_array[] = new int[100000];

// Do some computations with big_array and get a result. 
int result = compute(big_array);

// We no longer need big_array. It will get garbage collected when there
// are no more references to it. Since big_array is a local variable,
// it refers to the array until this method returns. But this method
// doesn't return. So we've got to explicitly get rid of the reference
// ourselves, so the garbage collector knows it can reclaim the array. 
big_array = null;

// Loop forever, handling the user's input
for(;;) handle_input(result);
}

#6


0  

In java there is no explicit way doing garbage collection. The JVM itself runs some threads in the background checking for the objects that are not having any references which means all the ways through which we access the object are lost. On the other hand an object is also eligible for garbage collection if it runs out of scope that is the program in which we created the object is terminated or ended. Coming to your question the method finalize is same as the destructor in C++. The finalize method is actually called just before the moment of clearing the object memory by the JVM. It is up to you to define the finalize method or not in your program. However if the garbage collection of the object is done after the program is terminated then the JVM will not invoke the finalize method which you defined in your program. You might ask what is the use of finalize method? For instance let us consider that you created an object which requires some stream to external file and you explicitly defined a finalize method to this object which checks wether the stream opened to the file or not and if not it closes the stream. Suppose, after writing several lines of code you lost the reference to the object. Then it is eligible for garbage collection. When the JVM is about to free the space of your object the JVM just checks have you defined the finalize method or not and invokes the method so there is no risk of the opened stream. finalize method make the program risk free and more robust.

在java中,没有明确的方法来进行垃圾收集。 JVM本身在后台运行一些线程,检查没有任何引用的对象,这意味着我们访问对象的所有方式都将丢失。另一方面,如果对象超出了我们创建对象的程序终止或结束的范围,则该对象也有资格进行垃圾收集。回到你的问题,方法finalize与C ++中的析构函数相同。 finalize方法实际上是在JVM清除对象内存之前调用的。您可以在程序中定义finalize方法。但是,如果在程序终止后完成对象的垃圾收集,则JVM将不会调用您在程序中定义的finalize方法。您可能会问到finalize方法有什么用?例如,让我们考虑您创建了一个对象,该对象需要一些流到外部文件,并且您明确地为此对象定义了一个finalize方法,该方法检查打开到该文件的流是否打开,如果没有则关闭流。假设在编写了几行代码后,您丢失了对该对象的引用。然后它有资格进行垃圾收集。当JVM即将释放对象的空间时,JVM只会检查您是否定义了finalize方法并调用该方法,因此不存在打开的流的风险。 finalize方法使程序无风险且更加健壮。