java编程优化-内存管理

[ 2010-05-13 19:34:32.0 | 作者: 随想 类别: 基础强化 ] 来源: 原创     浏览 2311
labels:java编程优化-内存管理 强引用 软引用 弱引用 java中的析构方法 jvm中对象的生命周期 垃圾回收
内存管理

垃圾回收,Jvm中的垃圾对象定义:
理解1:一个对象创建后放置在jvm的堆内存中.当永远不再引用这个对象时,他将被jvm在堆内存中回收,被创建对象不能再生,
同事也没办法通过程序语句释放他们.

理解2:当对象在jvm运行空间中无法通过根集合到达时,这个对象就被称作垃圾对象.
根集合是由类中的静态引用域与本地引用组成的.

jvm中对象的生命周期,分为7个阶段
创建阶段,应用阶段,不可视阶段,不可到达阶段,可收集阶段,终结阶段,释放阶段.

创建对象的几个规则:
	(1) 避免在循环体中创建对象,即使该对象占用内存空间不大.
	for(int i = 0; i < 10000; i++){
		Object obj = new Object();	//应当避免
		System.out.println("obj "+obj);
	}
	
	Object o = null;
	for(int i = 0; i < 100000; i++){
		o = new Object();	//仅在内存中保存一份对象的引用,可取
		System.out.println("obj "+o);
	}	
	-----------------------------------------------------------------------------
	public class demo{
	private List list = new ArrayList();
	public demo(){		
		list = new ArrayList();		//将对象初始化了2次,大大影响效率
	}
}
	
	(2) 尽量及时使对象符合垃圾回收标准
	不要采用过深的继承层次
	访问本地变量优于访问类中变量

强引用
	jvm内存管理器从跟引用集合出发遍寻堆中所有到达对象的路径.当到达某对象的任意路径都不含有引用对象时.被称为强引用.
	
软引用
	主要特点是具备较强的引用功能,只有当内存不够的时候,才会回收这类内存,因此在内存足够的时候,他们通常不被回收.
	另外,这些引用对象还能保证java跑出OutOfMemory异常之前,被设置成null.它可以用于实现一些常用的资源缓存,
	实现Cache的功能.保证最大限度的使用内存不引起OutOfMemory.
	public static void main(String[] args) {		
		A1 a1 = new A1();
		//使用a1
		System.out.println(a1.c);
		System.out.println(a1);
		//使用完a1 将它设置为soft引用类型,并且释放强引用
		java.lang.ref.SoftReference sr = new java.lang.ref.SoftReference(a1);
		a1 = null;
		System.out.println(a1);
		//下次使用的时候
		if(sr != null){
			a1 = (A1) sr.get();
		}else{
			//GC 由于低内存,已经释放a1 因此需要重新装在
			a1 = new A1();
			sr = new java.lang.ref.SoftReference(a1);
		}
		System.out.println(a1);
	}
	
弱引用
	对象与Soft引用对象的最大不同就在于,gc在进行回收时,需要通过算法检查是否回收soft引用对象,
	而对weak引用对象,gc总是进行回收,weak引用对象更容易,更快的呗gc回收.虽然,gc在运行时一定回收
	weak对象,但是复杂关系的weak对象群常常需要好几次gc的运行才能完成.weak引用对象常常用于
	map结构中.引用占用内存空间较大的对象.一旦该对象的强引用为null时,对这个对象引用就不存在了,
	gc能够快速地回收该对象空间.
	public static void main(String[] args) {
		Demo demo = new Demo();
		//使用....
		System.out.println(demo+" "+demo.c);
		//...使用完事将它设置为weak引用类型,并释放强引用
		java.lang.ref.WeakReference wr = new java.lang.ref.WeakReference(demo);
		demo = null;
		
		System.out.println("demo 没了 "+demo);
		
		//...下次使用的时候
		if(wr != null){
			demo = wr.get();
		}else{
			demo = new Demo();
		}
		//再次使用
		System.out.println(demo+" "+demo.c);
		
	}

虚引用	
	用途较少,主要用于辅助finalize函数的使用.
	
强调:
	在实际程序设计中一般很少使用弱引用和虚引用,使用软件的情况较多,这是因为软件引用可以加上jvm
	对内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题产生


不可视阶段
	当一个对象处于不可视阶段,说明我们在其他区域的代码中已经不可以在引用它了,
	强引用已经消失.例如,本地变量超出了可视范围.
	public void pore(){
		if(true){
			Object object = new Object();
			object.getClass();
		}
		if(true){			
			//这个区域对于object对象来说已经是不可视的了.
			//因此下面的代码在编译时就会引发错误
			object.getClass();
		}
	}
	如果一个对象在使用完之后,而且在其可视范围区域不在使用,此时应该主动将其设置为空,
	可以在object.getClass();下行加上object = null;这样一行代码强制将object对象设置为空值.
	这样做的意义在于,可以帮jvm及时地发现这个垃圾对象,并且可以及时地回收该对象所占用
	的系统资源.
	
	
数组空间的申请分为显示申请and隐式申请.
	public static void main(String[] args) {
		int[] as = new int[1024];
		//上面这行代码就是显示的相系统一次性的申请了大小为1kb的整数类型的内存空间
		//如果实际需要放入的字眼不足1024 就会浪费资源应该尽可能的用完就马上体现jvm回收
		
		String[] strs = new String[222222];
		SoftReference sf = new SoftReference(strs);
		//用完.....
		strs = null;				
	}

不要提前创建对象
	尽量在需要的时候在创建对象,重复的分配,构造对象可能会因为垃圾回收做额外的工作,
	降低性能.
	void fn(){
		int i;
		A a = new A();
		// 类A的对象a被创建
		//在判断语句之外并没有应用过a.
		if(true){
			// 类A的对象a再次应用
			a.findMethod();
			...
		}
		...
	}
	
	应该这么写
	void fn(){
		int i;
		...
		if(true){
			A a = new A();
			a.findMethod();
			...			
		}
	}
而在java语言中只有构造的概念,却没有析构的概念,这是因为理论上jvm负责对象的
析构方法,由于在java应用中开发的所有类都为Object的子类,因此用户类都从Object
因此finalize的最后一句通常是super.finalize().通过这种方式买我们可以实现从下到上
<FONT color="#5c585a" face=""">finalize调用.即先释放自身在主机往上释放.

package com.iwgod.chapter02.finalize;

public class A {
	Object a = null;
	public A(){
		a = new Object();
		System.out.println("构建A对象");
	}
	protected void destory(){
		a = null;		
		System.out.println("释放a对象");
	}
	protected void finalize() throws Throwable{
		destory();
		super.finalize();	//递归调用超类的finalize方法
	}
}

package com.iwgod.chapter02.finalize;

public class B extends A {
	String b = null;
	public B(){
		b = "aa";
		System.out.println("构建B对象");
	}
	protected void destory(){
		b = null;
		System.out.println("释放b对象");
		super.destory();
	}
	protected void finalize() throws Throwable{
		destory();
		super.finalize();		
	}
	
}

package com.iwgod.chapter02.finalize;

public class C extends B {
	Object c = null;
	public C(){
		c = new Object();
		System.out.println("创建C对象");
	}
	protected void destory(){
		c = null;
		System.out.println("释放c对象");
		super.destory();
	}
	protected void finalize() throws Throwable{
		destory();
		super.finalize();
	}
}

package com.iwgod.chapter02.finalize;

public class Test {

	/**
	 * @param args
	 * @throws Throwable 
	 */
	public static void main(String[] args) throws Throwable {
		// TODO Auto-generated method stub
		C c = new C();
		c.destory();
	}
	/**
	 * 注意到test类中实例化C对象的时候,其构造器产生了递归调用,并且是由几类开始
	 * 一次调用,初始化成员对象,而当调用c类的destory方法时系统通用产生了递归调用
	 * 但调用的顺序恰好相反.释放资源由子类开始,
	 * 由此可见我们在设计类时尽量避免在类的默认构造器中创建,初始化大量的对象,防止在调用其自身的构造器
	 * 时造成不必要的内存浪费,因为即使我们没有像调用父类的构造器创建大量无用的对象,但是喜用都会自动去
	 * 创建它们,而这些操作都是隐含的
	 */

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值