- 新建主类Main
package cn.sky.test;
public class Main {
public static void main(String[] args){
MyObject myObject = new MyObject();
myObject = null;
new Thread(()->{
while(true){
System.out.println(System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
- 新建MyObject类
package cn.sky.test;
public class MyObject {
byte[] bytes = new byte[1024*1024*100];
@Override
protected void finalize() throws Throwable {
System.err.println("finalized() begin");
Thread.sleep(5000);
System.err.println("finalized() end");
}
}
-
运行main方法,打开jvisualvm.exe工具,选择该java进程,进入“监视”视图(堆内存使用100M左右)。
-
点击“执行垃圾回收”按钮,观察监视视图变化和控制台输出。
控制台输出:每隔1s打印当前时间戳,点击按钮后打印“finalized() begin”,5秒后打印“finalized() end”。
监视视图变化:堆内存占用下降了一点,但是还维持在100M多一些,说明myObject对象在本次gc中没有被回收。 -
再次点击“垃圾回收按钮”,会发现堆内存使用情况减少了100M左右,myObject对象被回收了。
附代码文档解释:
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup.
The general contract of finalize is that it is invoked if and when the Java™ virtual machine has determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, except as a result of an action taken by the finalization of some other object or class which is ready to be finalized. The finalize method may take any action, including making this object available again to other threads; the usual purpose of finalize, however, is to perform cleanup actions before the object is irrevocably discarded. For example, the finalize method for an object that represents an input/output connection might perform explicit I/O transactions to break the connection before the object is permanently discarded.
The finalize method of class Object performs no special action; it simply returns normally. Subclasses of Object may override this definition.
The Java programming language does not guarantee which thread will invoke the finalize method for any given object. It is guaranteed, however, that the thread that invokes finalize will not be holding any user-visible synchronization locks when finalize is invoked. If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates.
After the finalize method has been invoked for an object, no further action is taken until the Java virtual machine has again determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, including possible actions by other objects or classes which are ready to be finalized, at which point the object may be discarded.
The finalize method is never invoked more than once by a Java virtual machine for any given object.
Any exception thrown by the finalize method causes the finalization of this object to be halted, but is otherwise ignored.
百度翻译如下:
当垃圾回收确定不再有对对象的引用时,由垃圾回收器在对象上调用。子类重写finalize方法以释放系统资源或执行其他清理。
finalize的一般约定是,当Java™ 虚拟机已确定,任何尚未终止的线程都无法再通过任何方式访问此对象,除非是由于某个其他对象或类的终结(该对象或类已准备好终结)所采取的操作。finalize方法可以执行任何操作,包括使此对象对其他线程再次可用;但是finalize的通常目的是在对象被不可撤销地丢弃之前执行清理操作。例如,表示输入/输出连接的对象的finalize方法可能会执行显式I/O事务,以便在永久丢弃该对象之前断开连接。
类对象的finalize方法不执行特殊操作;它只是正常返回。Object的子类可以覆盖这个定义。
Java编程语言不能保证哪个线程将调用任何给定对象的finalize方法。但是,可以保证调用finalize的线程在调用finalize时不会持有任何用户可见的同步锁。如果finalize方法引发了一个未捕获的异常,那么该异常将被忽略,并且该对象的finalize将终止。
在为某个对象调用finalize方法之后,在Java虚拟机再次确定没有任何方法可以让任何尚未终止的线程访问该对象之前,不会采取进一步的操作,包括其他对象或类可能要完成的操作,此时对象可能会被丢弃。
finalize方法从未被Java虚拟机针对任何给定对象多次调用。
finalize方法引发的任何异常都会导致此对象的终结被暂停,否则将被忽略。