现在的位置: 首页 > 综合 > 正文

java优化-java内存管理

2014年01月28日 ⁄ 综合 ⁄ 共 2528字 ⁄ 字号 评论关闭

JVM管理两种类型的内存,堆内存和栈内存,其中堆内存主要放实例化的对象和变量。栈内存主要是存放在类中声明的静态或非静态的方法。

JVM对象的7种状态:

1、创建阶段

2、应用阶段

3、不可视阶段

4、不可到达阶段

5、可收集阶段

6、终结阶段

7、释放阶段

    

下面就针对这7个阶段来分别说明对象的状态,首先是创建阶段,对象创建主要可以分为5部:

1、为对象分配存储空间 (在堆内存中分配空间)

2、开始构造对象

3、递归调用其超累的构造方法 (每一个java类都有一个父类,递归调用父类的构造方法)

4、进行对象的初始化与变量的初始化 (存入相应的存储空间)

5、执行对应的构造方法体 

    

针对以上5个阶段,创建对象应该注意

1、避免在循环体中创建对象

2、尽量及时使对象符合垃圾回收的标准

3、不要采用过深的继承

4、访问本地变量优于访问类中的变量

看下面的例子:

public class Test {

	public static void main(String[] args) {
		long l1 = System.currentTimeMillis();
		for(int i=0; i<1000; i++) {
			Test t1 = new Test();
			System.out.println("i:" + (i+1) + " " + t1);
		}
		long l2 = System.currentTimeMillis();
		long start = l2 -l1;
		
		long l3 = System.currentTimeMillis();
		Test t = null;
		for(int i=0; i<1000; i++) {
			t = new Test();
			System.out.println("i:" + (i+1) + " " + t);
		}
		long l4 = System.currentTimeMillis();
		long end = l4 -l3;
		
		System.out.println("第一次时间差:" + start);
		System.out.println("第二次时间差:" + end);
		System.out.println("第一次减去第二次:" + (start - end));
	}
}

运行结果:不同的电脑运行的速度不同

    第一次时间差:63

    第二次时间差:31

第一次减去第二次:32

       

     可见采用下面的速度要比之前的快的多,原因是,第一种创建了1千个引用,每个对象都有自己的引用,这需要增加系统垃圾回收时计算的成本,而第二种方法,只创建一份引用,一份对象用完之后,对他的引用也就随之消失,那么JVM可以直接判断他是垃圾对象,给予回收。

还有同一个对象不要初始化多次,如以下

private List<String> list = new ArrayList<String>();

public void f() {

list = new ArrayList<String>();

            ……

}

是不可取的,以下是正确的:

private List<String> list = new ArrayList<String>();

public void f() {

         ……

}

在开发的过程中,每个细节都会导致软件的性能。

          在应用阶段,java的对象可以分为以下几种,强引用,弱引用,软引用,虚引用。

          强引用:强引用是指JVM内存管理器从根集合出发遍历堆中所有到达路径的对象,当到达这个对象的任意路径都不含有引用对象时,这个对象被称为强引用。系统至少维持着一个强引用,所有对该对象的引用都是强引用,除非调用了别的引用。

         软引用:主要特点是有较强的引用只有当内存不足时才被被回收。软引用最大的一个好处是保证在系统在抛出OutOfMemory异常之前,被置为NULL,所有软引用一般会被用在常用资源的缓存。

以下是应用方法:

      

public void softReference() {
	Test test = new Test();
	//使用test
	SoftReference<Test> sr = new SoftReference<Test>(test);
	//把test置为空
	test = null;
		
	//下次使用时
	if(sr != null) {
		test = sr.get();
	} else {
		//由于系统内存过低释放test,需要重新装载
		test = new Test();
		sr = new SoftReference<Test>(test);
	}
}

        弱引用:弱引用对象与软引用的区别是:GC在进行回收时,需要通过算法检查是否要回收软引用的对象,而对于弱引用时,总是进行回收。所以弱引用比软引用更快,更容易被回收,但是复杂的弱引用需要多次才能回收。弱引用对象长用于Map结构中,引用占有内存较大的对象,一旦该对象的强引用为NULL时,对这个对象的引用也就不存在了,GC能够快速回收这个对象。弱引用时用WeakReference对象来进行,和软引用相似。

虚引用:虚引用的引用较少,主要用于辅助finalize函数的使用。

我们在实际开发中,一般很少使用虚引用和弱引用,使用软引用的情况较多是因为软引用可以加速JVM对垃圾回收的速度,可以维护系统的安全,避免内存溢出。

不可视阶段:

当一个对象处于不可视阶段,说明我们在其他区域的代码已经不能引用他,其强引用消失,看以下例子:

    public void process() {

try {

Object obj = new Object();

} catch (Exception e) {

e.printStackTrace();

}

//在以下obj不在此区域中,程序报错

//obj.

}

如果一个对象在可见区域内不再使用时,可以把这个对象显示设置为空(obj=null),这样可以强制obj为空,帮助JVM快速发现立即对象,并及时的回收系统资源。

不可到达阶段:

处于不可到达的对象在虚拟机的对象引用根集合中再也找不到直接或间接的引用,这些变量一般都是所有线程栈中的临时变量,所有已装载的类静态变量或对本地代码接口的引用。

可收集阶段、终结阶段和释放阶段

1、回收器发现该对象已经不可到达

2、Finalize方法已经执行

3、对象空间已经被重用

抱歉!评论已关闭.