为什么要使用垃圾收集器?
类似类型为什么要收集一样(参考http://boy00fly.iteye.com/blog/1108420)。java程序运行的过程中,越来越多的对象在堆中生成,占用的内存越来越大,如果不收集的话,到最后结果可想而知;即使堆内存足够,请求分配新对象时可能不得不增大堆空间的大小,虽然可以使用的总空闲空间是足够的,这是因为堆中没有连续的空闲空间放得下新的对象,在一个虚拟内存系统中,增长的堆所需的额外分页(或交换)空间会影响运行程序的性能。
使用垃圾收集器的优缺点
优点:1. 可以提高生产率。
程序员可以从复杂的释放内存空间的重担中解救出来。
2. 保持程序的完整性
垃圾收集是Java安全策略的一个重要部分,java程序员不可能因失误(或者故意)错误地释放内存而导致Java虚拟机崩溃。
缺点:使用java垃圾收集堆,有一个潜在缺陷是它加大了程序负担,可能影响程序性能。因为Java虚拟机必须追踪哪些对象被正在执行的程序所引用,并且动态地终结并释放不再被使用的对象。和明确释放不再被使用的内存比起来,这个活动会需要更多的CPU时间。并且,在垃圾收集环境下,程序员对安排CPU时间来释放无用对象缺乏控制。
哪些对象是垃圾对象?
首先要检测出垃圾对象。垃圾检测通常通过建立一个根对象的集合并且检查从这些根对象开始的可触及性来实现。如果正在执行的程序可以访问到的根对象和某个对象之间存在引用路径,这个对象就是可触及的。对于程序来说,根对象总是可以访问的。从这些根对象开始,任何可以被触及的对象都被认为是"活动"的对象。无法被触及的对象被认为是垃圾。
下面来谈谈什么是根对象集合?
Java虚拟机的根对象集合根据实现不同而不同,总体分为以下几个来源:
1. 局部变量中的对象引用和栈帧的操作数栈(以及类变量中的对象引用)。这个总是包含的。
2. 被加载的类的常量池中的对象引用,比如字符串。被加载的类的常量池可能指向保存在堆中的字符串,比如类名字、超类的名字、超接口的名字、字段名、字段特征签名、方法名或者方法特征签名。
3. 传递到本地方法中的、没有被本地方法"释放"的对象引用。(本地方法接口,本地方法通过简单地返回释放引用,或者显示地调用一个回调函数来释放传递来的引用,或者是这两者的结合。)
4. Java虚拟机运行时数据区中从垃圾收集器的堆中分配的部分。举例来说,在某些实现中,方法区中的类数据本身可能被存放在使用垃圾收集器的堆中,以便使用和释放对象。同样的垃圾收集算法来检测和卸载不再被引用的类。
任何被根对象引用的对象都是可触及的,从而是活动的。另外,任何被活动的对象引用的对象都是可触及的。程序可以访问任何可触及的的对象,所以这些对象必须保留在堆里面。任何不可触及的对象都可以被收集,因为程序没有办法来访问他们。
在Java虚拟机实现中,有些垃圾收集器可以区别真正的对象引用和看上去像合法对象引用的基本类型(比如一个int)之间的差别。(例如一个int整形,如果被解释是一个本地指针,可能指向堆中的一个对象)可是某些垃圾收集器仍然选择不区分真正的对象引用和"伪装品",这种垃圾收集器被称为保守的(conservative),因为他们可能不能总是释放一个不再被引用的对象。对保守的垃圾收集器,有时候垃圾对象也被错误地判断为活动的,因为有一个看上去像是对象引用的基本类型"引用"了对象。保守的收集器使垃圾收集速度提高了,因为有一些垃圾被遗忘了。
区分活动对象和垃圾对象的两个基本方法是引用计数和跟踪。引用计数垃圾收集器通过为堆中的每个对象保存一个计数来区分活动对象和垃圾对象。这个计数记录下了对那个对象的引用次数。跟踪垃圾收集器实际上追踪从根节点开始的引用图。在追踪中遇上的对象以某种方式打上标记,当追踪结束时,没有被打上标记的对象就被判定是不可触及的,可以被当做垃圾收集。
垃圾收集算法
垃圾收集算法主要有以下几种
1、引用计数收集器
2、跟踪收集器
3、压缩收集器
4、拷贝收集器
5、按代收集的收集器
6、自适应收集器
7、火车算法(Sun公司的HotSpot虚拟机就是使用的此算法)
终结
在Java语言里面,一个对象可以拥有终结方法:这个方法是垃圾收集器在释放对象钱必须运行的。这个可能存在的终结方法使得任何Java虚拟机的垃圾收集器要完成的工作更加复杂。
给一个类加上终结方法,只需要简单地再类中声明一个方法:
class Example {
protected void finalize() throws Throwable {
//*****
super.finalize();
}
}
垃圾收集器必须检查他所发现的不再被引用的对象是否存在finalize()方法。
因为,存在终结方法时,Java虚拟机的垃圾收集器必须每次在收集时执行一些额外的步骤。首先,垃圾收集器必须使用某种方法检测出不再被引用的对象(称作第一遍扫描)。然后,它必须检查它检测出的不再被引用的对象是否声明了终结方法。如果时间允许的话,可能在这个时候垃圾收集过程就着手处理这些存在的终结方法。
当执行了所有的终结方法之后,垃圾收集器必须从根节点开始再次检测不再被引用的对象(称为第二遍扫描)。这个步骤是必要的,因为终结方法可能"复活"了某些不再被引用的对象,使他们再次被引用了。最后垃圾收集器才释放那些在第一次和第二次扫描中发现的都没有被引用的对象。
为了减少释放内存的时间,在扫描到某些对象拥有终结方法和运行这些终结方法之间,垃圾收集器可以有选择地插入一个步骤。一旦垃圾收集器执行了第一遍扫描,并且找到一些不再被引用的对象需要执行终结,他可以运行一次小型的跟踪,从需要执行终结的对象开始(而非从根节点开始)。任何满足如下条件的对象-------->从根节点开始不可触及(在第一遍扫描中检测出),以及从将要被终结的对象开始不可触及---------这些对象不可能在执行终结方法时复活,他们可以立即被是释放。
如果一个带有终结方法的对象不再被引用,并且他的终结方法运行过了,垃圾收集器必须使用某种方法记住这一点,而不能再次执行这个对象的终结方法。如果这个对象被它自己的终结方法或者其他对象的终结方法复活了,稍后再次不再被引用,垃圾收集器必须像对待一个没有终结方法的对象一样对待它。
使用Java编程时,必须记住一点:是垃圾收集器运行对象的终结方法。因为总是无法预测何时对象会被垃圾收集,所以也无法预测对象的终结方法何时运行。应该避免编写这样的程序,即程序的正确性依赖于对象的终结方法所运行的时机。比如,如果不再被引用的对象的终结方法释放了一个以后程序中将用到的资源,这个资源将直到垃圾收集器运行了这个对象的中终结方法后才能够使用。如果程序在垃圾收集器有机会终结这个不再被引用的对象之前需要这个资源,这个程序将无法得到该资源。
对象可触及性的生命周期
在版本1.2之前,在垃圾收集器来看,堆中的没一个对象都有三种状态之一:可触及的,可复活的,以及不可触及的。
可触及的,不可触及的这两种装载大家都清楚的。那什么状态才是”可复活的“?它在从根节点开始的追踪图中不可及,但是有可能在垃圾收集器执行某些终结方法时触及。所以说可复活状态的对象或许转化为可触及的状态,或者前进到不可触及状态。但是不可触及状态标志着不但对象不再被触及,而且也不可能通过任何终结方法复活,不可触及的对象不再对程序传递执行产生影响,可以自由地回收他们所占据的内存。
在后续版本中,上述三种状态扩充的新的状态,例如:在1.2版本中扩充了三个新状态:软可触及,弱可触及,以及影子可触及。这里就不再详述了。
以上内容参考《深入Java虚拟机》。
补充:以上讲的是对象的回收问题,大家有没有想过对象可以怎么创建?即类的实例化!
以下4种是显式实例化的途径:
1. 明确地使用new操作符
2. 调用Class或者java.lang.reflect.COnstructor对象的newInstance()方法
3. 调用任意对象的clone()方法
4. 通过java.io.ObjectInputStream类的getObject()方法反序列化
隐式实例化的途径:
1. 保存命令行参数的String对象。(main函数的参数)
2. Java虚拟机装载每一个类型,它会暗中实例化一个Class对象来代表这个类型。
3. 执行包含字符串连接操作符的表达式产生对象。
4. ........
5. ........
6. ........
分享到:
相关推荐
《自己动手写Java虚拟机》是Java核心技术系列中的一本书,旨在帮助读者深入理解Java虚拟机(JVM)的工作原理,以及如何从零开始构建一个简单的JVM。这本书通过实践的方式,让读者能够亲手实现虚拟机的关键功能,从而...
11. **垃圾回收(GC)**:Java自动进行内存管理,程序员无需手动释放内存,垃圾回收器负责识别并回收不再使用的对象。 12. **JVM**:Java虚拟机是Java程序的运行环境,它负责解析字节码、执行指令,并实现了内存...
Java是世界上最流行的编程语言之一,尤其在企业级应用开发领域占据主导地位。JDK(Java Development Kit)是Java编程的...记得理论结合实践,多动手编写代码,遇到问题时查阅文档或在线资源,不断提升自己的编程能力。
Java作为全球最流行的编程语言之一,其面试环节对于求职者来说至关...通过学习这个合集中的资料,你可以全面提高自己的Java技术水平,为英文面试做好充分准备,同时也为未来在思科这样的国际化公司工作打下坚实的基础。
了解JVM的工作原理,包括类加载机制、垃圾回收(GC)以及内存模型,是成为一名合格Java开发者的基础。 2. **基础语法**:包括数据类型、变量、运算符、控制结构(如if、for、while)、方法、类和对象等。这些构成了...
面试中会考察JVM内存模型(堆、栈、方法区、本地方法栈等)、垃圾回收机制(GC、分代收集、引用类型)、性能优化(JVM参数调优、内存泄漏检测)等内容。深入理解JVM可以帮助开发者写出更高效、稳定的代码。 这个...
Java笔试题目是企业在招聘IT专业人士时常常采用的一种筛选方式,尤其在Java开发领域,各大公司如腾讯、Google、百度、华为、中兴和网易等都设有相关的技术测试。这些题目通常涵盖Java语言基础、数据结构、算法、面向...
4. **内存模型与垃圾回收**:Java内存区域(堆、栈、方法区、本地方法栈、程序计数器)、GC(垃圾收集器)原理、内存泄漏与内存溢出的问题分析。 5. **IO与NIO**:传统IO流的读写操作,缓冲区的概念,NIO(New ...
因此,不仅要熟记理论知识,还要通过实际项目锻炼自己的动手能力。 总之,这个压缩包为Java开发者提供了一个全面的复习指南,通过深入学习和实践,可以极大地提高面试成功率,助你在Java开发的职业道路上更进一步。
Java虚拟机(JVM)是Java程序运行的核心,它负责解析和执行字节码,管理内存,以及实现各种运行时特性。...记得实践是检验理论的最好方式,动手操作并结合代码理解这些概念,会使你的Java编程技能更上一层楼。
【Java教程:利用Java进行各种示例】 Java是一种广泛使用的高级编程语言,以其跨平台、面向对象和安全性著称。本教程"java-tutorials"旨在帮助开发者深入理解Java语言的各种特性,并通过丰富的示例来实践这些知识。...
Java面试宝典是Java开发者在求职过程中不可或缺的参考资料,它涵盖了Java编程语言的核心概念、框架、设计模式以及面试常问问题。以下是一些基于Java面试的详细知识点: 1. **Java基础** - 类与对象:理解面向对象...
JavaAcademy2020 是一个以Java编程语言为主题的培训课程或学习资源集合,可能包含了一系列关于Java学习的教程、实战项目、课件、代码示例等。这个压缩包很可能是为了帮助学员或者自学者深入理解Java语言,提升编程...
核心技术课程 自己动手写Web服务器(Socket、多线程)、ashx模式Web开发、ViewState、Cookie、Session、Http协议、Web开发基本原则、XSS漏洞防范、Request对象、Response对象、Server对象、虚拟路径、HttpHandler...