我需要知道什么时候在JVM中调用finalize()方法。我创建了一个测试类,当finalize()方法被重写时写入文件。它没有被执行。有人能告诉我为什么它不能执行吗?
当前回答
一般来说,最好不要依赖finalize()来做任何清理等。
根据Javadoc(值得一读),它是:
当垃圾回收确定对象不再有引用时,由垃圾回收器在对象上调用。
正如Joachim指出的,如果对象总是可访问的,那么在程序的生命周期中,这可能永远不会发生。
此外,垃圾收集器不保证在任何特定时间运行。一般来说,我想说的是finalize()可能不是最好的方法,除非有特定的事情需要它。
其他回答
由于JVM调用finalize()方法存在不确定性(不确定被重写的finalize()是否会被执行),为了研究目的,观察finalize()调用时发生的情况的更好方法是通过命令System.gc()强制JVM调用垃圾收集。
具体来说,finalize()在对象不再使用时被调用。但是当我们试图通过创建新对象来调用它时,它的调用是不确定的。因此,为了确定起见,我们创建了一个空对象c,它显然没有未来的用途,因此我们看到对象c的finalize调用。
例子
class Car {
int maxspeed;
Car() {
maxspeed = 70;
}
protected void finalize() {
// Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
// Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection
System.out.println("Called finalize method in class Car...");
}
}
class Bike {
int maxspeed;
Bike() {
maxspeed = 50;
}
protected void finalize() {
System.out.println("Called finalize method in class Bike...");
}
}
class Example {
public static void main(String args[]) {
Car c = new Car();
c = null; // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
Bike b = new Bike();
System.gc(); // should clear c, but not b
for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
System.out.print("\t" + b.maxspeed);
if (b.maxspeed > 50) {
System.out.println("Over Speed. Pls slow down.");
}
}
}
}
输出
Called finalize method in class Car...
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51Over Speed. Pls slow down.
52Over Speed. Pls slow down.
53Over Speed. Pls slow down.
54Over Speed. Pls slow down.
55Over Speed. Pls slow down.
56Over Speed. Pls slow down.
57Over Speed. Pls slow down.
58Over Speed. Pls slow down.
59Over Speed. Pls slow down.
60Over Speed. Pls slow down.
61Over Speed. Pls slow down.
62Over Speed. Pls slow down.
63Over Speed. Pls slow down.
64Over Speed. Pls slow down.
65Over Speed. Pls slow down.
66Over Speed. Pls slow down.
67Over Speed. Pls slow down.
68Over Speed. Pls slow down.
69Over Speed. Pls slow down.
70Over Speed. Pls slow down.
注意:即使打印到70,并且在此之后对象b在程序中没有被使用,也不确定b是否被JVM清除,因为“调用的finalize方法在类Bike…”没有打印。
一般来说,最好不要依赖finalize()来做任何清理等。
根据Javadoc(值得一读),它是:
当垃圾回收确定对象不再有引用时,由垃圾回收器在对象上调用。
正如Joachim指出的,如果对象总是可访问的,那么在程序的生命周期中,这可能永远不会发生。
此外,垃圾收集器不保证在任何特定时间运行。一般来说,我想说的是finalize()可能不是最好的方法,除非有特定的事情需要它。
什么时候在Java中调用finalize()方法?
finalize方法将在GC检测到对象不再可达之后调用,并且在它实际回收对象所使用的内存之前调用。
If an object never becomes unreachable, finalize() will never be called on it. If the GC doesn't run then finalize() may never be called. (Normally, the GC only runs when the JVM decides that there is likely to enough garbage to make it worthwhile.) It may take more than one GC cycle before the GC determines that a specific object is unreachable. (Java GCs are typically "generational" collectors ...) Once the GC detects an object is unreachable and finalizable, it is places on a finalization queue. Finalization typically occurs asynchronously with the normal GC.
(JVM规范实际上允许JVM永远不运行终结器……前提是它不回收对象所使用的空间。以这种方式实现的JVM将是残废的/无用的,但这种行为是“允许的”。)
其结果是,依赖最终确定来完成必须在特定时间框架内完成的事情是不明智的。根本不使用它们是“最佳实践”。应该有更好的(即更可靠的)方法来做你在finalize()方法中试图做的事情。
终结的唯一合法用途是清理应用程序代码丢失的与对象相关的资源。即使这样,您也应该尝试编写应用程序代码,使其在一开始就不会丢失对象。(例如,使用Java 7+ try-with-resources来确保close()总是被调用…)
我创建了一个测试类,当finalize()方法被重写时写入文件。它没有被执行。有人能告诉我为什么它不能执行吗?
这很难说,但有几种可能性:
对象不会被垃圾收集,因为它仍然是可达的。 对象不会被垃圾收集,因为GC在测试结束之前不会运行。 对象由GC找到,并由GC放置在终结队列中,但是在测试结束之前,终结不会完成。
类,在其中重写finalize方法
public class TestClass {
public TestClass() {
System.out.println("constructor");
}
public void display() {
System.out.println("display");
}
@Override
public void finalize() {
System.out.println("destructor");
}
}
finalize方法被调用的几率
public class TestGarbageCollection {
public static void main(String[] args) {
while (true) {
TestClass s = new TestClass();
s.display();
System.gc();
}
}
}
当内存被转储对象重载时,gc将调用finalize方法
运行并查看控制台,在那里你不会发现finalize方法被频繁调用,当内存超载时,finalize方法将被调用。
An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection. Generally an object becomes eligible for garbage collection in Java on following cases:
该对象的所有引用显式设置为空,例如object = null 对象在块内创建,一旦控件退出该块,引用就会离开作用域。 父对象设置为空,如果一个对象持有另一个对象的引用,并且当您将容器对象的引用设置为空时,子对象或包含对象自动符合垃圾收集的条件。 如果一个对象只有通过WeakHashMap的活动引用,那么它就有资格进行垃圾收集。
推荐文章
- Eclipse调试器总是阻塞在ThreadPoolExecutor上,没有任何明显的异常,为什么?
- Java生成两个给定值之间的随机数
- 如何有效地从数组列表或字符串数组中删除所有空元素?
- 比较JUnit断言中的数组,简洁的内置方式?
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令