一、总叙
没有被任何线程和对象引用的对象会被回收。
二、哪些情况可以被回收
1、置空变量
public class GCTest {
private String name;
public GCTest(String name){
this.name=name;
}
/**
* java提供了一种机制,对象刚要被垃圾回收之前运行一些代码,这段代码位于名为finalize()的方法内。
*/
@Override
public void finalize(){
System.out.println("gc 回收了对象 "+name);
}
public static void main(String[] args) throws Throwable{
GCTest gct=new GCTest("n1");
//置空 触发回收条件
gct=null;
//调用gc加快回收
System.gc();
Thread.sleep(10000);
}
}
手动将对象置为null,测试时调用gc,触发回收打印出结果,显示对象n1被回收了。

2、局部变量
方法创建的对象作用域在方法中,出了方法作用域失效,变量无法被引用成为没有被引用的对象,可被回收,但作为返回值返回的对象例外。
public class GCTest3 {
private String name;
public GCTest3(String name){
this.name=name;
}
private void test3(){
GCTest3 gct=new GCTest3("n2-sub");
gct.say("Hello");
}
private void say(String word){
System.out.println(name + " say "+word);
}
@Override
public void finalize(){
System.out.println("gc 回收了对象 "+name);
}
public static void main(String[] args) {
GCTest3 gct=new GCTest3("n2");
//调用方法
gct.test3();
//调用方法结束,触发回收
System.gc();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

3、重置变量
创建了对象1和对象2,随后对象1=对象2,原本对象1的引用失效,符合回收条件。
public class GCTest4 {
private String name;
public GCTest4(String name){
this.name=name;
}
@Override
public void finalize(){
System.out.println("gc 回收了对象 "+name);
}
public static void main(String[] args) {
GCTest4 gct1=new GCTest4("gct1");
GCTest4 gct2=new GCTest4("gct2");
gct1=gct2; //gct1的引用被重置,成为被回收的对象
System.gc();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

三、集合对象回收
1、不完全回收情况
集合使用完成后,如果不调用clear方法,集合中的元素无法被回收。
import java.util.ArrayList;
import java.util.List;
public class GCListTest {
private String name;
public GCListTest(String name){
System.out.println("new "+name);
this.name=name;
}
@Override
public void finalize(){
System.out.println("gc 回收了对象 "+name);
}
public static void main(String[] args) throws InterruptedException{
int count=0;
while(true){
List<GCListTest> list=new ArrayList<GCListTest>();
for(int i=0;i<3;i++){
GCListTest t=new GCListTest("n"+count+"-"+i);
list.add(t);
}
System.out.println("exe "+count++);
if(count==3){
break;
}
}
System.gc();
Thread.sleep(20000);
}
}

2、完全回收
使用完后调用clear,所有元素置空引用,符合回收条件
import java.util.ArrayList;
import java.util.List;
public class GCListTest {
private String name;
public GCListTest(String name){
System.out.println("new "+name);
this.name=name;
}
@Override
public void finalize(){
System.out.println("gc 回收了对象 "+name);
}
public static void main(String[] args) throws InterruptedException{
int count=0;
while(true){
List<GCListTest> list=new ArrayList<GCListTest>();
for(int i=0;i<2;i++){
GCListTest t=new GCListTest("n"+count+"-"+i);
list.add(t);
}
//清空引用,触发回收
list.clear();
System.out.println("exe "+count++);
if(count==3){
break;
}
}
System.gc();
Thread.sleep(20000);
}
}


本文详细介绍了Java中的垃圾回收机制,包括对象何时可以被回收的三种情况:置空变量、局部变量过期以及重置变量。同时,通过示例说明了集合对象的回收,分析了不完全回收和完全回收的区别。通过对内存管理的理解,有助于优化Java应用程序的性能。
5075

被折叠的 条评论
为什么被折叠?



