Java - 该对象何时卸载?

发布于 2024-12-08 21:28:07 字数 226 浏览 0 评论 0原文

这是我的代码:

    LinkedList <Mono> list = new LinkedList ();

    list.add(new Mono (2, 2));
    list.add(new Mono (1, -1));
    list.remove (1);

现在,当列表中的第二项被删除时,该对象是否被销毁? IE,它经历垃圾收集吗?

Here is my code:

    LinkedList <Mono> list = new LinkedList ();

    list.add(new Mono (2, 2));
    list.add(new Mono (1, -1));
    list.remove (1);

Now, when the second item in the list is removed, is the object destroyed? IE, it undergoes garbage collection?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

回忆凄美了谁 2024-12-15 21:28:07

编辑新问题:

是的,当没有剩余的强引用时,该对象将有资格进行垃圾回收。然而,JVM 会尝试大批量地清理垃圾,因此实际上可以在以后的任意时间收集垃圾(或者如果 JVM 在 GC 处理之前终止,则永远不会收集)

旧答案

类卸载是一种罕见的事件,并且通常不会及时发生(如果有的话)。

具体来说,即使在它符合收集条件之后,它也不会与像 Mono 实例这样的“正常”新对象一起被收集 - 它通常是在一个特殊的不同的池子里(Oracle JVM 中的 PermGen)

您应该假设一旦加载了一个类,它将永远保持加载状态。一旦您进入容器中的 Web 应用程序,情况并不总是如此,但在这些环境中工作过的任何人都可以告诉您它的工作情况(不)。

EDIT for new question:

Yes, the object will be eligible for garbage collection when there are no strong references remaining. However the JVM will try to do clean up garbage in big batches, so it could actually get collected at any arbitrary later time (or never if the JVM terminates before GC gets around to it)

Old answer:

Class unloading is a rare event, and will generally not happen in a timely manner (if at all.)

Specifically, even after it becomes eligible for collection it won't get collected along with "normal" new objects like your Mono instances - it's often in a special different pool (PermGen in the Oracle JVM)

You should assume that once a class is loaded it will stay loaded forever. Once you get into web applications in containers this is not always true, but anyone that has worked in those environments can tell you generally how well it (doesn't) work.

森林迷了鹿 2024-12-15 21:28:07

Java 中的垃圾收集通常是不确定的,何时发生,以及当 GC 周期发生时 GC 将驱逐(“释放”)哪些符合条件的对象。

因此,唯一可靠的规则是:

  1. 只要对象强可达,它就将保持可用(不会被GC回收/释放/驱逐)。 (请参阅《Java 虚拟机内部》第 9 章 这意味着什么——总的来说,非常好的读物,如果有点过时。)

在发布的代码中,remove 将产生第二个对象 new Mono(1, -1)< /代码> 是有资格回收,因为不再有任何对它的强引用(该对象不再是强可达的)。实际的驱逐(如果发生)将在“稍后的某个时间”发生,甚至可能不是下一个 GC 周期。使用终结器 (ick) 使问题进一步复杂化。

请注意,对象永远不会保证会被GC(例如,JVM 可能只是正常终止),并且特定 GC 实现的确切语义可能有所不同,但仍然是一致的虚拟机——这一切都取决于可达性。

快乐编码。

Garbage Collection in Java is generally non-deterministic insofar as when it will occur and which eligible objects the GC will evict ("free") when a GC cycle does occur.

The only reliable rule is thus:

  1. An object will remain available (will not be GC'ed/freed/evicted) as long as it is strongly-reachable. (See "The Reachability Lifecycle of Objects" in Chapter 9 of Inside the Java Virtual Machine for what this means -- very good reading in general, if a tad dated.)

In the posted code the remove will result in the second object new Mono(1, -1) being eligible for reclamation as there are no longer any strong references to it (the object is no longer strongly-reachable). The actual eviction (if it occurs) will happen "sometime later" and may not even be the next GC cycle. Using finalizers (ick) further complicates the matter.

Note that an object is never guaranteed to be GC'ed (the JVM may just terminate [ab]normally, for instance) and the exact semantics of particular GC implementation can differ and still be a conforming virtual machine -- it all comes down to reachability.

Happy coding.

乜一 2024-12-15 21:28:07

你的意思是当对象被卸载时?

空列表仍然是列表,因此它会保留在内存中。当你去的时候它会被清除:

list=somethingElse;

这是假设您没有将其他任何内容分配给列表。

就类定义本身而言,它应该永远保留在内存中。类定义位于永久代中。

作为旁注。此时列表无法被垃圾回收。因为如果你清除它之后你可以添加东西。

Do you mean when the Object is unloaded?

An empty list is still a list, so it'll stay in memory. It is cleared when you go:

list=somethingElse;

That is assuming that you don't assign anything else to be list.

As far as the class definition itself, it should stay in memory forever. Class definitions are in the permanent generation.

As a side note. list cannot be garbage collected at that point. Because you can add things to it after if you clear it.

生活了然无味 2024-12-15 21:28:07

将第二个对象从列表中删除后,将有资格进行 gargabe 收集,因为将不再有对它的引用..因此超出了范围。

希望这有帮助

the second object will be elligible for gargabe collection after removing it from the list, since there will be no more references to it .. hence out of scope .

hope this helped

§对你不离不弃 2024-12-15 21:28:07

答案很多,所以这是我的观点。想一想“范围”,这是计算机语言中的一个概念,它描述了您可以在何处以及何时访问指定的内存位。

这是您的原始代码,其中添加了据称删除的第二个列表成员:

LinkedList <Mono> list = new LinkedList ();

list.add(new Mono (2, 2));
list.add(new Mono (1, -1));
list.remove (1);
list.remove (2);`

在 list.remove(2) 处,仍然可以引用对象“list”。当然,它是空的,但是您可能决定向其中添加一个新的 Mono。您可以,因为“list”仍然在范围内,所以“list”不会被回收。

与此相比:

{
  LinkedList <Mono> list = new LinkedList ();

  list.add(new Mono (2, 2));
  list.add(new Mono (1, -1));
  list.remove (1);
  list.remove (2);`
}

在右大括号之后,“list”不能再被引用。 “list”是在该范围内声明的,当退出该范围时,“list”与范围本身一起从命名空间中删除。在那个这一点上,垃圾收集可能发生,因为没有人可能再次使用“list”。

密切注意对象的范围。如果您想影响垃圾收集,请将对象的范围限制在使用它们的区域。碰巧,这也是一种很好的编程风格。

Lots of answers, so here's my spin. Think about "scope", a concept in computer languages that describes where and when you can access a named bit of memory.

Here's your original code, with your purported removal of the second list member added:

LinkedList <Mono> list = new LinkedList ();

list.add(new Mono (2, 2));
list.add(new Mono (1, -1));
list.remove (1);
list.remove (2);`

At the point of list.remove(2), the object "list" can still be referenced. Sure, it's empty, but then you might decide to add a new Mono to it. You can because "list" is still in scope, so "list" is not reclaimed.

Compare to this:

{
  LinkedList <Mono> list = new LinkedList ();

  list.add(new Mono (2, 2));
  list.add(new Mono (1, -1));
  list.remove (1);
  list.remove (2);`
}

After the closing brace, "list" can no longer be referenced. "list" was declared inside that scope, and when the scope was exited, "list" was removed from the namespace along with the scope itself. At that point, garbage collection could happen, since no one could possibly use "list" again.

Keep an eye on the scope of your objects. If you want to influence garbage collection, keep the scope of your objects limited to the region where they are used. As it happens, that is good programming style too.

懒的傷心 2024-12-15 21:28:07

我猜人们对你使用的术语感到困惑。我相信您是在问您的 Mono 对象是否会被“删除”/“垃圾收集”。

让我们看一下您正在调用的 remove(1)...

这是您正在调用的删除函数,如 java.util.LinkedList 中所定义

public E remove(int index) {
    return remove(entry(index));
}

:上面的函数调用以下内容(请看我在代码中的注释):

private E remove(Entry<E> e) {
if (e == header)
    throw new NoSuchElementException();

    E result = e.element;
    e.previous.next = e.next; //Preceding element refers now to the one after the element to be removed;
    e.next.previous = e.previous; //Next element refers now to the one before the one to be removed;
    e.next = e.previous = null; //Element to be removed doesn't refer to anything anymore;
    e.element = null;
    size--;
    modCount++;
    return result;
}

在您调用的函数终止后,将无法再引用您的 Mono(1, -1) 。该 Mono 对象不再可访问。这意味着它将有资格进行垃圾收集。请记住,“合格”可能意味着它永远不会被垃圾收集...有关 GC 的更多信息 这里

I guess people got confused with the terminology you used. I believed you are asking if your Mono object will be "deleted"/"garbage collected".

Let's take a look at the remove(1) that you are invoking...

This is the remove function that you are calling as defined in java.util.LinkedList:

public E remove(int index) {
    return remove(entry(index));
}

The function above calls the following (look at my comments in the code):

private E remove(Entry<E> e) {
if (e == header)
    throw new NoSuchElementException();

    E result = e.element;
    e.previous.next = e.next; //Preceding element refers now to the one after the element to be removed;
    e.next.previous = e.previous; //Next element refers now to the one before the one to be removed;
    e.next = e.previous = null; //Element to be removed doesn't refer to anything anymore;
    e.element = null;
    size--;
    modCount++;
    return result;
}

After the function you call terminates, there is no way to refer to your Mono(1, -1) anymore. That Mono Object is not accessible anymore. This means that it will become eligible for Garbage Collection. Keep in mind that "eligible" might mean that it never be garbage collected... More on GC here.

不再让梦枯萎 2024-12-15 21:28:07

简单的答案是,Java 对象何时被垃圾回收对您来说应该无关紧要。您需要知道的唯一一件事是,在您的程序内存不足之前,它被垃圾收集 ...假设该对象无法到达。

复杂的答案还包括其他内容:

  • 垃圾收集器通常在您无法预测的时间运行。

  • 您可以调用System.gc()来建议JVM立即运行GC,但是:

    • JVM 可能会忽略此提示,并且

    • 这样做通常是个坏主意。 (运行 GC 的成本很高,而且您的应用程序没有足够的信息来了解从效率角度来看何时最好执行此操作。)

  • GC 的任何特定运行都不能保证回收所有无法访问的对象。 GC 有很多“智能”,旨在使 GC 尽可能高效,或减​​少“暂停”时间。 “聪明”之一是不要每次都对整个堆进行 GC。

  • 无法保证 GC 一定会运行,或者它会在 JVM 关闭之前运行。

  • 由于上述原因,编写一个应用程序依赖在特定时间回收/删除的特定对象是一个坏主意。 p>


(在内存管理中应该关注的一件事是存储泄漏;例如,当您的应用程序保留对不需要的对象的引用时,以防止这些对象变得无法访问。但这不是您的问题所在。)

The simple answer is that it should not matter to you when a Java object is garbage collected. The only thing that you need to know is that it will get garbage collected before your program runs out of memory ... provided that the object is unreachable.

The complicate answer includes other things:

  • The garbage collector typically runs at a time that you can't predict.

  • You can call System.gc() to suggest that the JVM runs the GC run now, but:

    • the JVM may ignore this hint, and

    • it is generally a bad idea to do this. (Running the GC is expensive, and your application has insufficient information to know when it is best to do this from an efficiency standpoint.)

  • Any particular run of the GC is not guaranteed to reclaim all unreachable objects. The GC has a lot of "smarts" that are aimed at making GC as efficient as possible, or reducing "pause" times. One of the "smarts" is to not GC the entire heap every time.

  • There are no guarantees that the GC will run at all, or that it will run before the JVM is shutdown.

  • Because of the above, it is a bad idea to write an application so that it depends on a specific object being reclaimed / deleted at a specific time.


(The one thing that should concern you in memory management is storage leaks; e.g. when your application keeps references to unwanted objects that prevent those objects from ever becoming unreachable. But that's not what your question is about.)

貪欢 2024-12-15 21:28:07

类“Mono”无法卸载,因为仍然存在对它的引用。列表的类型引用它,并且列表中仍然有一个元素。

我想你并不是想问类是否被卸载,而是问实例是否被“卸载”。类的每个实例、每个对象都在堆上分配。当对象不再使用时,它在堆中占用的空间可以被回收。然而,这不会立即发生。我所知道的所有 JVM 实现都使用垃圾收集器来清理内存。为了真正简化这里的事情:当堆上没有更多可用空间来创建新对象时,垃圾收集器就会启动并检查堆的哪些部分仍在使用中。不再使用的部件可以重新用于新物体。

因此,不再使用的对象的内存只有在垃圾收集器启动时才会被回收。这是无法预测的。

The class "Mono" cannot be unloaded since there are still references to it. The type of the list refers to it and there is still one element in the list.

I suppose you did not mean to ask whether the class is unloaded, but whether the instance is "unloaded". Each instance of a class, each object, is allocated on the heap. When the object is no longer in use, the space that it occupies in the heap can be reclaimed. This does not happen immediately however. All JVM implementations that I know use a garbage collector to clean up the memory. To really simplify things here: when there is no more space free to create a new object on the heap, the garbage collector kicks in and will check which parts of the heap are still in use. The parts that are no longer in use, can be reused for new objects.

So, the memory from an object that is no longer in use, will only be reclaimed when the garbage collector kicks in. And this is something that cannot be predicted.

剩余の解释 2024-12-15 21:28:07

你的意思是 Mono 的实例有资格进行垃圾收集,还是 list 的实例有资格进行垃圾收集?

mono 的实例在被删除时将有资格进行垃圾回收(假设代码没有创建对它的引用。

该列表不符合垃圾回收的条件,因为它被清空了。空列表不能被垃圾回收,因为它 。

正如其他人指出的那样,垃圾收集器不一定会立即运行

Do you mean is the instance of Mono eligible for garbage collection or is the instance of list eligible for garbage collection?

The instance of mono will be eligible for garbage collection when it is removed (assuming that the code has not created over references to it.

The list is NOT eligible for garbage collection just because it is emptied. An empty list cannot be garbage collected because it is a valid object that can read and written to again.

An as others have pointed out. We are talking about eligible for garbage collection. The garbage collector does not necessarily run immediately.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文