`
javawebsoa
  • 浏览: 409416 次
社区版块
存档分类
最新评论

Java学习笔记(对象的释放)

阅读更多

对于基本类型变量来说,因为都被分配在内存栈中,因此释放不是问题,而且都会被及时地释放.但对于引用类型来说,就不一样了.
Java提供了基本的对象内存回收机制-垃圾回收器.下面看看如何工作:
首先我们必须了解一点,引用类型的变量和基本类型的变量一样,都是被分配到内存栈里的,只是引用类型的变量在栈中保存的是
一个引用地址(指针),该引用地址所指的堆内存就是实际的对象存放区。
Java的垃圾回收器对于Java程序来说是外部程序,是独立运行的,因此必须有一种机制,让垃圾回收器知道哪些对象(堆中)
是不再被用的,最简单的方法当然是对对象引用计数:
一个对象被一个对象变量引用,其对象引用计数就加1,如果一个对象的引用变量(在栈中)超出生存期,被释放时,对象引用计数
就减1,这样,垃圾回收器就可以根据对象引用计数来判断对象是否可以被收回。看起来这种方法确实比较简单,但实际上,
这种方式还是有很多问题的:
1)如果对象变量都在栈中,上述机制当然没问题。但实际上对象变量可以是另一个对象的成员,而且对象本身也可以包含其它
对象类型的成员变量,这样就会形成一个复杂的引用关系网,这个引用关系网还可能会包含循环引用的情况,就会很容易导致一
些对象在整个程序运行期间都不会被回收,从而产生大量的内存泄露;
2)同步问题。垃圾回收器工作时,如果程序也在工作,也在分配或操作对象,比如一个对象的引用计数虽然为0,垃圾
回收器回收该对象,但同时,这个对象又被引用到一个新的对象变量,就会产生不可预知的错误。为了防止这种冲突,垃圾回
收器工作时程序就必须停止工作。这就会带来另外一个问题,程序运行效率降低。

现在这种利用对象引用计数方式的垃圾回收方式已经很少单独使用。

另外一种方法是采用对象跟踪技术的方法:
垃圾回收器工作时,从程序栈内存中的引用变量开始,遍历对象引用,标记对象可达。那么不可达的对象都可以回收掉。
这种方法解决了循环引用的问题,回收效率比较高,但也同样有以下问题:
1)没有解决垃圾回收器和程序之间的同步问题,垃圾回收器工作期间程序必须停止运行;
2) 每次垃圾回收时,都需要遍历所有的对象,用时会比较长;

当然还有很多垃圾回收策略,大家可以搜一下,虽然垃圾回收对于程序员来说,大部分时间是透明的,但理解这些机制,其实也可以
对我们处理实际问题时提供一种借鉴。
无论是那种回收机制,对于程序员来说,有两个地方是必须关注的:
1)我们的对象什么时候被回收(垃圾回收器运行的不可控);
2)Java产生的对象没问题,但我们自己分配的内存(主要是调用其它语言代码库,比如C++)怎么释放。
垃圾回收器工作的触发是根据其对内存使用的监控来确定的,当内存空间小于某个阀值时才触发垃圾回收。对于大部分的情况,这应该
不是问题,但如果我们的对象使用了第三方稀缺资源,比如数据库链接,或者我们需要在对象释放的时候做一些清除(比如擦除在界面上的
绘图)工作,我们该怎么办?一种办法当然是主动出击,比如数据库链接,打印机释放等,但有些情况下,我们还是无法主动出击的,比如
一个对象使用了数据库链接,但这个对象被多个其它对象共享,你就很难主动出击释放链接了。对于这种情况,Java提供了另外一种机制,
就是为每个对象提供一个finalize()方法,该方法由垃圾回收器调用(虽然你自己也可以调用,但不建议这样做,原因同无法主动出击类似)。
这样对于对象释放后需要做的清理工作就可以在这个方法中进行。但要注意垃圾回收器对finalize()方法的调用是有限制的,比如每个对象只调用
一次这个方法,因此,我们必须留意对象"复活"所带来的问题。
对于什么时候我们的对象会被回收的问题,虽然我们可以调用System.gc()来建议(注意,只是建议)垃圾回收器进行回收工作,但实际上
对我们来说,还是不可控的,因此:
1)对于资源,特别是稀缺资源的释放,我们还是应该尽量主动出击来完成;
2)对于调用其它语言代码库,也尽量主动出击进行对象释放,如果不行,至少也要在finalize()方法中完成;

下面的例子,是抄书本上的,用来演示垃圾回收的不确定性(我稍微做了修改):

public class Chair {
	
		static boolean gcrun = false;
		static boolean f = false;
		static int created = 0;
		static int finalized = 0;
		int i;
		Chair() {
		i = ++created;
		if(created == 47)
		System.out.println("Created 47");
		}
		protected void finalize() {
		if(!gcrun) {
		gcrun = true;
		System.out.println(
		"Beginning to finalize after " +
		created + " Chairs have been created=>"+i);
		}
		if(i == 47) {
		System.out.println(
		 "Finalizing Chair #47, " +
		 "Setting flag to stop Chair creation");
		 f = true;
		}
		finalized++;
		if(finalized >= created)
		System.out.println("All " + finalized + " finalized");
		}
}


public class GarbageC {
	public static void main(String[] args) {
		
		while(!Chair.f) {
		   new Chair();
		   new String("To take up space");
		}
		System.out.println(
		"After all Chairs have been created:\n" +
		"total created = " + Chair.created +
		", total finalized = " + Chair.finalized);
		String theMethString ="after";
		if(theMethString.equals("before")) {
		 	System.out.println("gc():");
			System.gc();
		 	System.out.println("runFinalization():");
			System.runFinalization();
		}
		System.out.println("bye!");
		if(theMethString.equals("after"))
		  System.runFinalizersOnExit(true);
		}
}



分享到:
评论

相关推荐

    Java学习笔记

    JAVA健壮性高,它去掉指针、内存申请和释放、无条件转移语句,但有引用的概念,实际传递的是内存地址 (大小为4字节) JAVA提供多线程、提供动态下载程序代码的机制、安全性,它的操作以字节码(class)文件形式保存

    Java并发编程(学习笔记).xmind

    acquire获得许可(相当于P操作),release释放许可(相当于V操作) 应用场景 (1)二值信号量可用作互斥体(mutex) (2)实现资源池,例如数据库连接池 (3)使用信号量将任何一种容器变成...

    net学习笔记及其他代码应用

    答:两个对象,一个是“xyx”,一个是指向“xyx”的引用对象s。 38.abstract class和interface有什么区别? 答: 声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为...

    java虚拟机学习笔记之垃圾收集

    java程序是运行在java虚拟机当中的,在java虚拟机的堆中运行着程序所创建的对象。可以使用new,newarray,anewarray,multianewarray指令来创建对象,但是没有明确的代码来释放这些对象所使用的空间。垃圾收集是自动...

    2009达内SQL学习笔记

    如:prod_price="" 这种写法是错的(不要受到corejava的影响) prod_price=NULL 这种写法是错的(不要受到corejava的影响) prod_price IS NULL 这种写法才是对的 NVL:处理空值,把空值转化为指定值。可转化为日期、...

    JDBC学习笔记

    JDBC学习笔记 JDBC基本用法 JDBC Java DataBase Connectivity Java语言连接数据库 本质 sun公司制定的一套接口 面向接口编程 降低耦合度,提高可扩展能力 JDBC编程六步 注册驱动 即将连接的是哪一个数据库型号 ...

    JavaScript笔记.doc

    2、鼠标按下与鼠标释放事件(onMouseDown、onMouseUp) 10 3、预览页面(onMouseOver): 11 4、图像切换(onMouseOver、onMouseOut) 11 5、接收键盘输入(keyPress事件): 12 6、用鼠标点亮文本 12 五、处理图像与动画 13...

    JDBC课堂笔记.md

    mysql的jar包及学习方法, 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar 1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下 2.右键-->Add As Library 2. 注册驱动 3. 获取数据库连接...

    Google《Android性能优化》学习笔记(下)

    1)Memory,GC,andPerformance众所周知,与C/C++需要通过手动编码来申请以及释放内存有所不同,Java拥有GC的机制。Android系统里面有一个GenerationalHeapMemory的模型,系统会根据内存中不同的内存数据类型分别执行...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 第一章 Oracle入门 一、 数据库概述 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今五十年前。简单来说是本身可视...

    程序员面试刷题的书哪个好-thinkingInJava:学习《thinkinginjava》一书

    2.java有一个垃圾回收器,用来监视所有new创建的对象,并辨别那些不在被引用的对象,释放这些对象的内存空间。 3.当一个类的成员变量是基本类型时,JVM会默认将其初始化为对应的初值,但是最好自行进行初始化。 成员...

Global site tag (gtag.js) - Google Analytics