什么决定了垃圾收集器何时实际进行垃圾收集?它是在特定的时间之后还是在使用了一定量的内存之后发生?或者有其他因素吗?
什么决定了垃圾收集器何时实际进行垃圾收集?它是在特定的时间之后还是在使用了一定量的内存之后发生?或者有其他因素吗?
Java 1.0和1.1虚拟机使用标记-清除收集器,这可能会在垃圾回收后使堆成为碎片。从Java 1.2开始,虚拟机切换到分代收集器,其具有更好的碎片整理行为(参见Java理论与实践:垃圾收集和性能)。
因此,Java实际上已经有了分代GC很久了。Java 6中新的是Garbage-First(G1)垃圾收集器,可在Java 6u14中使用。根据声称发布于1.6.0_14的文章: 它不是默认启用的。并行收集器仍然是默认GC,对于普通家庭用途来说,它是最有效的GC。 G1旨在成为并发收集器的替代品。它被设计为更可预测,并允许使用内存区域进行快速分配。
当JVM没有足够的内存空间运行时,垃圾收集器会运行并删除不必要的对象以释放内存。
不必要的对象是指没有其他引用(地址)指向它们的对象。
一个对象有主要4种方式可以被标记为可回收。
Null Referencing
The garbage collector can delete an object when the reference variable
of the object is assigned null
as its value.
A a = new A();
a = null;
Re-assigning
When another object is assigned to the reference variable of an object, the older referenced object can be deleted by the garbage collector.
A a = new A(100);
a =new A(200);
Local Scope
If an object is created inside a block, then that object will be eligible for garbage collection outside that block.
if(condition){
A a = new A();
}
Isolation
An object can contain a reference to another object, but there must be at least one reference (address) variable for those objects in the stack, otherwise all those objects are eligible for garbage collection.
class A{
A r;
A(int i){
//something
}
}
A a1 = new A(100);
a1.r = new A(101);
a1.r.r = new A(102);
a1.r.r.r = a1;
a1 = null //all ojects are eligible to garbage collector
您可以尝试此小程序来检查GC的行为
public class GCTest {
final int NELEMS = 50000;
void eatMemory() {
int[] intArray = new int[NELEMS];
for (int i=0; i<NELEMS; i++) {
intArray[i] = i;
}
}
public static void main (String[] args) {
GCTest gct = new GCTest();
// Step 1: get a Runtime object
Runtime r = Runtime.getRuntime();
// Step 2: determine the current amount of free memory
long freeMem = r.freeMemory();
System.out.println("free memory before creating array: " + freeMem);
// Step 3: consume some memory
gct.eatMemory();
// Step 4: determine amount of memory left after consumption
freeMem = r.freeMemory();
System.out.println("free memory after creating array: " + freeMem);
// Step 5: run the garbage collector, then check freeMemory
r.gc();
freeMem = r.freeMemory();
System.out.println("free memory after running gc(): " + freeMem);
}
}
可能的输出 -- 在您的情况下可能会有所不同
free memory before creating array: 4054912
free memory after creating array: 3852496
free memory after running gc(): 4064184
这很大程度上取决于您实际使用的垃圾收集器,它的调整方式以及许多输入参数。
有关HotSpot Garbage Collector(Java常用的垃圾收集器)及其调整方式的详细信息,请查看此链接
垃圾回收器在需要资源时运行,并且定期运行,您可以通过告知何时是收集CPU的好时机来影响它,使用System.gc()。
您可以通过显式地将引用设置为null来帮助垃圾回收器,例如,通过为您的对象提供分配资源的init()
方法和显式清理这些资源并将其引用设置为null的cleanup()
方法。通过自己将引用设置为null,您可以防止垃圾回收器不得不查找具有更多路径到根的对象群集。