胡八一之Java(五):java内存回收,
胡八一之Java(五):java内存回收,
当一个对象在堆内存中运行时,有以下三种状态:
可达状态:当一个对象有一个以上的引用变量引用它,程序可以通过引用变量来调用对象的属性和方法。在有向图中,这就属于可达。
可恢复状态:如果一个对象没有任何变量再引用它,那么它将先进入可恢复状态。系统的垃圾回收机制准备回收该对象所占的内存,在回收该对象之前,系统会调用可恢复状态的对象finalize方法进行资源清理,如果系统调用该方法让对象有一个以上的变量重新引用它,则这个对象就会再变成可达状态,否则变成不可达状态。
不可达状态:当对象没有引用变量引用它时,而且调用finalize方法也没有使其变为可达状态,则系统将会回收其对象所占的内存空间。
一个对象可以被一个方法的实例变量引用,可以被其它类的类变量引用,也可以被其他对象的实例对象引用。当某个对象被其他类的类变量所引用时,只有当这个类销毁时,该对象才会进入可销毁状态;当某个对象被其他对象引用时,只有这个对象销毁时或进入不可达状态时,这个对象才会进入不可达状态。
java对象对象的引用有四种:强引用、软引用、弱引用,虚引用
其中我们编程经常可以采纳的有两种:强引用、软引用。
强引用:程序创建一个对象,并把这个对象赋给一个引用变量。这种引用状态是Java编程中最常见的,被强引用的对象绝不会被垃圾回收机制回收,即使内存非常紧张,jvm也不会回收这种强引用所引用的对象,所以这也是Java内存泄漏的主要原因之一。
(内存泄漏:程序运行过程中会不断地分配内存空间,那些不在使用的内存空间将会被回收,从而保证系统可以再次使用这些内存,如果存在无用的内存没有被回收回来,那就是内存泄漏)
软引用:通过SoftReference类来实现,当系统的空间足够时,对象不会被回收,当内存紧张时,内存才会回收对象。
package aaaaa;
import java.lang.ref.SoftReference;
class Person {
String name;
int age;
public Person(String name,int age){
this.age=age;
this.name=name;
}
public String toString(){
return "Person[name]:="+name+", age="+age;
}
}
public class Test{
public static void main(String args[]) throws Exception{
SoftReference<Person>[] people =new SoftReference[100000];
for(int i =0;i<people.length;i++){
people[i] =new SoftReference<Person>(new Person("名字"+i,(i+1)*4%100));
}
System.out.println(people[2].get());
System.out.println(people[4].get());
//通知系统进行垃圾回收
System.gc();
System.runFinalization();
//垃圾回收机制运行会,
System.out.println(people[2].get());
System.out.println(people[4].get());
}
}
运行结果:
Person[name]:=名字2, age=12
Person[name]:=名字4, age=20
Person[name]:=名字2, age=12
Person[name]:=名字4, age=20
此时内存没有达到紧张状态,所以没有清除2和4对象,可通过在cmd中为JVM指定较小的堆内存来达到效果,如下
java -Xmx2m -Xms2m 类名
Java内存管理小技巧:
1、尽量使用直接量
当使用字符串,Byte,Short,Integer,Float,Double,Boolean,Character包装类的实例时不应该使用new来创建对象,而应该直接
使用
如:
String a = new String("hello");
这种方式会创建一个“hello"字符串,而且JVM的字符缓冲池会缓存这个字符串,除此之外,a所引用的String对象底层还包含一个char数组,char数组里依次存放了hello 的每个字符。
String a ="hello";
而这种就不会产生char数组。
2、使用StrinBuilder和StringBuffer来进行字符串连接
String 代表字符序列不可变字符串,而StringBuffer和StringBuilder代表字符序列可变字符串。
如果使用String字符串来连接字符串,则会产生大量零时字符串。
3、尽早释放无用对象,将对象显式的设置为null
public void info(){
Object obj =new Object();
System.out.println(obj.toString());
System.out.println(obj.hashCode());
obj =null;
//下面是一些耗内存的操作,完全需要释放上面对象的内存空间
....
}
4、尽量少用静态变量
静态变量生命周期与类同步,当遇到常驻内存的class ,一旦被创建,就会常驻内存。
5、避免在经常调用的方法中,循环中创建Java对象
6、缓存经常使用的对象
7、尽量不要使用finalize方法
8、考虑使用SoftReference
相关文章
- 暂无相关文章
用户点评