深入理解java内存回收(一) 哪些对象可以被回收?

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

一、总叙

没有被任何线程和对象引用的对象会被回收。

二、哪些情况可以被回收

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);
	}
}

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值