垃圾收集器(内存回收器)的行为线
Java 程序员不需要监视内存分配,因为垃圾收集器会自动管理内存。垃圾收集器由 Java 虚拟机 (JVM) 运行。垃圾收集器是一个低优先级进程,它定期运行并释放不再需要的对象使用的内存。不同的 JVM 有不同的垃圾收集算法。使用了多种算法,例如:引用计数算法或标记和抓取算法。
在 Java 中运行垃圾收集器
当可用内存较低时,JVM 通常会运行垃圾收集器。但垃圾收集器的运行并不能保证总是有足够的空闲内存。如果恢复后仍然没有足够的内存,JVM 会抛出 OutOfMemoryError 异常。请注意,JVM 在抛出异常之前必须至少运行一次垃圾收集器。您可以请求垃圾收集器在 Java 中运行,但不能强制执行此操作。
请求运行垃圾收集器
要发出请求,您可以调用以下方法之一:
System.gc()
Runtime.getRuntime().gc()
适合运行垃圾收集器
当对象不再可供活动流使用时,必须将其丢弃。一个物体可能会在不同的情况下被处置:
- 如果引用某个对象的引用类型变量被设置为“0”,并且没有其他引用对该对象进行处理,则必须释放该对象。
- 如果创建引用一个对象的引用类型变量来引用另一个对象,并且没有其他引用对该对象进行处理,则必须释放该对象。
- 当方法退出时,在方法中本地创建的对象将被丢弃,除非它们是从该方法导出的(即作为异常返回或抛出)。
- 如果没有一个对象可供活动线程使用,则相互引用的对象可能会被处置。
让我们看一个例子:
public class TestGC
{
public static void main(String [] args)
{
Object o1 = new Integer(3);
Object o2 = new String("Tutorial");
o1 = o2;
o2 = null;
}
}
在此示例中
Integer
,最初由 o1 引用的对象(整数)可以在第 3 行之后处理,因为 o1 现在引用该对象
String
(字符串)。即使创建 o2 来引用 null,该对象
String
(字符串)也是不可回收的,因为 o1 引用了它。
最终确定
finalize()
Java 技术允许您在垃圾收集器从内存中检索对象之前使用方法(finalize) 进行必要的清理。当垃圾收集器确定不再有对该对象的引用时,垃圾收集器会对该对象调用此方法。这是在 class 中描述的
Object
,这意味着它被所有类继承。子类重写该方法
finalize()
以将其自身从系统资源中释放出来或进行另一次清理:
protected void finalize() throws Throwable
如果方法抛出未注册的异常
finalize()
,则该异常将被忽略并且该对象的终结将停止。该方法
finalize()
在对象的生命周期内只会被调用一次。可以对
finalize()
任何物体使用某种方法来保护其免遭处置。但在这种情况下,垃圾收集器不再
finalize()
为此对象激活。
finalize()
在对象被垃圾收集之前,该方法始终会被调用一次。然而,对于给定对象,该方法
finalize()
可能不会在其存在的整个持续时间内被激活,因为它可能不会受到处置。
概括
在本节中,我们研究了垃圾收集过程,这是 Java 语言中的一种内存管理技术。不能强制垃圾收集。我们了解了使对象符合回收条件的不同方法,并了解了
finalize()
在垃圾收集器回收对象之前调用该方法。
锻炼
问: 第 7 行之后有多少物品将被处置?
public class TutorialGC
{
public static void main(String [] args)
{
Object a = new Integer(100);
Object b = new Long(100);
Object c = new String("100");
a = null;
a = c;
c = b;
b = a;
}
}
答案选项: A. 0 B. 1 C. 2 D. 3 E. 代码无法编译
正确选项: B
说明:在第 1、2、3 行创建的三个对象中,只有该对象
Integer
必须在第 7 行末尾。最初引用对象的变量引用 a在第 5 行
Integer
引用了该对象。因此,必须在第 5 行之后处理该对象,因为没有引用它的变量。变量和引用第6行和第7行中的对象和对象,因此它们是不可回收的。
String
Integer
b
c
String
Long
GO TO FULL VERSION