是否可以强制对象的垃圾收集?(java)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以强制对象的垃圾收集?(java)相关的知识,希望对你有一定的参考价值。
Java中提供了一些和垃圾收集打交道的类,而且提供了一种强行执行垃圾收集的方法--调用System.gc(),但这同样是个不确定的方法。Java 中并不保证每次调用该方法就一定能够启动垃圾收集,它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。 参考技术A 强制对象的垃圾收集?你是说强行的把这个对象给回收了,还是说强行启动垃圾回收器。如果是前者估计不能了,c里面有析构函数可以给你手动直接调用,把这个对象给ko了,但是java只有个finalize,但是这个方法只是在该对象被ko之前被动调用的,你主动调用这个方法该对象也不会被ko的。
强行启动垃圾回收机制System.gc(),你如果想立刻清理某个对象的话,只要释放该对象的引用,然后强行启动垃圾回收那这个对象就被ko了,但是这种手段会真占用系统资源,所以不建议使用,反正最好方法就是别一次性产生大量的垃圾,垃圾太多环卫工人忙不过来,那你就不能正常干活了!~ 参考技术B 不可以吧.调用System.gc(),用invalidate(),和把对象置空,都只是建议虚拟机进行垃圾回收.~然后虚拟机看心情清理垃圾.~ 并非强制立刻执行垃圾回收~~.. 参考技术C 垃圾收集重要特点:
(1)垃圾收集发生的不可预知性:由于实现了不同的垃圾收集算法和采用了不同的收集机制,所以它有可能是定时发生,有可能是当出现系统空闲CPU资源时发生,也有可能是和原始的垃圾收集一样,等到内存消耗出现极限时发生,这与垃圾收集器的选择和具体的设置都有关系。
(2)垃圾收集的精确性:主要包括2 个方面:(a)垃圾收集器能够精确标记活着的对象;(b)垃圾收集器能够精确地定位对象之间的引用关系。前者是完全地回收所有废弃对象的前提,否则就可能造成内存泄漏。而后者则是实现归并和复制等算法的必要条件。所有不可达对象都能够可靠地得到回收,所有对象都能够重新分配,允许对象的复制和对象内存的缩并,这样就有效地防止内存的支离破碎。
以上是我数上的资料。
我的答案:
可以强制对对象进行垃圾收集,用
System.gc(); 和 System.runFinalization();来收集。
但是你不可预知他在什么时候开始调用收集器。
如果你对我真诚的回答满意的话,请给我多加分,如果有什么疑问的话,请给我留言。QQ也可以全天在线108424683 参考技术D 不可以 调用System.gc(),只是建议虚拟机进行垃圾回收.然后虚拟机是否回收并不确定。 并非强制立刻执行垃圾回收。当然你也可以用 死循环 一直到它回收为止 不过这样划不来
Java - 可以对正在执行方法的对象进行垃圾收集吗?
【中文标题】Java - 可以对正在执行方法的对象进行垃圾收集吗?【英文标题】:Java - Can objects which are executing methods be garbage-collected? 【发布时间】:2012-12-16 04:59:31 【问题描述】:在 Java 中,我不假思索地做了以下事情:
public class Main
public void run()
// ...
public static void main(String[] args)
new Main().run();
但是,最近我开始不确定这样做是否安全。毕竟,Main
对象在创建后就没有引用了(嗯,有 this
引用,但这算不算?),所以看起来垃圾收集器可能会在删除对象时删除该对象。它正在执行某事。所以也许main
方法应该是这样的:
public static void main(String[] args)
Main m = new Main();
m.run();
现在,我很确定第一个版本可以正常工作,而且我从来没有遇到过任何问题,但我想知道在所有情况下这样做是否安全(不仅在特定的 JVM 中,而且最好根据语言规范对此类情况的规定)。
【问题讨论】:
作为记录,Microsoft CLR 中的等效构造可以在方法仍在执行时收集。见When does an object become eligible for garbage collection? 可能重复:Does the object which is the entry point of a Java program get garbage collected? @DanielPryden - 也许这两个问题都在问同一个问题,但这个问题的问法更加清晰,并且比引用的问题产生了更有用的答案。 @dj18:同意——这就是我没有投票结束的原因。但是我觉得交叉引用是一个有用的补充,所以我添加了一个评论。 【参考方案1】:如果正在执行对象方法,则表示有人拥有该引用。所以不,在执行方法时不能对对象进行 GC。
【讨论】:
+1 保留的对象是那些可以从线程根访问的对象,因此它们不能被定义为 GC。 嗯,我怀疑是这样的,但我遇到的问题是在任何时候都没有明确的引用(即变量)指向创建的对象。这是否意味着,就GC而言,只要在语句中使用了对象(例如使用.
运算符调用对象上的方法),这都算作隐式持有对该对象的引用?
你还有这个参考。这算作正常参考。
来自 JLS 的报价会给您 +1(如果我能找到,我会稍后添加)。
请做。我没兴趣看。【参考方案2】:
大部分垃圾收集是透明的。它可以消除手动内存管理的不必要的复杂性。因此,它看起来不会被收集,但实际发生的事情更加微妙。
简单来说,编译器可能会完全忽略对象的构造。 (通过编译器,我的意思是比 javac 更低级别的编译器。字节码将是源的字面音译。)更模糊的是,垃圾收集通常在单独的线程中运行,并且实际上将未访问的对象作为正在运行的方法删除。
如何观察到这一点?终结者中的常见嫌疑人。它可以与对象上运行的方法同时运行。通常,您可以在终结器和普通方法中使用 synchronized
块来解决这个问题,这引入了必要的 happens-before 关系。
【讨论】:
【参考方案3】:m 只是一个存储了引用的变量。这将被程序员用来进一步使用同一个对象在同一个对象上编写逻辑。
在执行时,程序将被转换为 OP-CODES / INSTRUCTIONS 。 这些指令将引用对象(毕竟它是一个内存位置)。 如果 m 存在,将通过 INDIRECT REFERENCE 访问对象的位置。 如果 m 不存在,则参考为 DIRECT。
所以在这里,对象被 CPU 寄存器使用,而与引用变量的使用无关。
在执行流程在 main() 函数的范围内之前,这将是可用的。
此外,根据 GC 过程,GC 只会从内存中删除对象,一旦 GC 确定该对象将不再被使用。
每个对象都有机会生存多次(取决于情况和算法)。一旦机会的数量结束,那么只有对象被垃圾收集。
简单来说,最近使用的对象将有机会留在内存中。 旧对象将从内存中删除。
所以给出你的代码:
public class Main
public void run()
// ...
public static void main(String[] args)
new Main().run();
对象不会被垃圾回收。
另外,例如,请尝试查看匿名类示例。或者来自 AWT / SWING 中事件处理的示例。
在那里,你会发现很多这样的用法。
【讨论】:
【参考方案4】:接受的答案不正确。对象是否可以被 GC 取决于您的 public void run() // ...
方法是否引用了类实例(this)。试试:
public class FinalizeThis
private String a = "a";
protected void finalize()
System.out.println("finalized!");
void loop()
System.out.println("loop() called");
for (int i = 0; i < 1_000_000_000; i++)
if (i % 1_000_000 == 0)
System.gc();
// System.out.println(a);
System.out.println("loop() returns");
public static void main(String[] args)
new FinalizeThis().loop();
上面的程序总是输出
loop() called
finalized!
loop() returns
在 Java 8 中。但是,如果您取消注释 System.out.println(a)
,输出将更改为
loop() called
a
loop() returns
这次没有GC,因为调用的方法引用了实例变量(this.a)。
你可以看看this answer
【讨论】:
以上是关于是否可以强制对象的垃圾收集?(java)的主要内容,如果未能解决你的问题,请参考以下文章