java内存概述
对象和变量的生存空间
生存空间包括堆空间和栈空间
对象的生存空间
所有的对象都存活于可垃圾回收的堆上,而对象引用变量都是放在栈上
变量的生存空间
变量分为实例变量和局部变量
局部变量存在于栈空间上
实例变量存在于对象所属的堆空间上
比如A类有一个字段B,那么申请A对象的堆空间时将会为字段B分配对应的堆空间
java垃圾回收机制
(1)java使用垃圾收集器监视java程序的运行
(2)java使用一系列
软指针来跟踪对象的各个引用,并用一个
对象表将这些软指针映射为对象的引用
(3)java的
垃圾收集器以单独的线程在后台运行, 并依次检查每个对象. 通过更改对象表项,垃圾收集器可以标记对象,移除对象,移动对象或检查对象.
例子
Object sobj=new Object();
Object sobj=null;//此时第1行的sobj符合垃圾收集器的收集标准
Object sobj=new Object();
sobj=new Object();//此时第3行的sobj符合垃圾收集器的收集标准
(4)需要注意
(A)调用System类中静态的gc()方法可以运行垃圾收集器,但这样并不能保证立即回收指定对象.
(B)java的垃圾回收机制是为所有的java应用进程服务的,而不是为某个特定的进程服务的.
(5)一个有用的模型
如果将对象考虑为有向图的顶点,将引用关系考虑为有向图的边,有向边从引用者指向被引用对象.
另外,每个线程对象可以作为一个图的起始顶点,例如,大多程序从main程序开始执行,那么该图就是以main进程顶点开始的一棵子树.
在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象.如果某个对象(连通子图)与这个根顶点不可达(注意该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收.
例图
java内存泄露
在java中,内存泄露就是存在一些被分配的对象,这些对象有下面两个特点
(1)对象是可达的,即在有向图中,存在通路可以与其相连
(2)对象是无用的,即程序以后不会再使用这些对象.
如果对象满足这两个条件,这些对象就可以判定为java中的内存泄露,这些对象不会被GC回收,然而它们却占用内存
内存泄露的例子
Vector v=new Vector(10);
for(int i=1;i<100;i++)
{
Object o=new Object();
v.add(o);
o=null;
}
//此时,所有的Object对象都没有被释放,因为变脸v引用这些对象
在这个例子中,循环申请Object对象,并将所申请的
对象放入一个Vector中.如果仅仅释放引用本身,那么Vector
仍然引用该对象,所以这个对象对GC来说是不可回收的.
因此,如果对象加入到Vector后,还必须从Vector中删除,
最简单的方法就是将Vector对象设置为null
注
本文参考资料
<<Head First Java>>Second Edition
<<java面试宝典>>第二版