GC是什么?Java初学者可能很少听到这个名词,但它的中文肯定听过:垃圾回收,英文全称为:Garbage Collection。
看过上一篇《Java虚拟机内存管理》的朋友想一下,GC的主要对象是哪几个内存区域呢?
上一篇提到,Java内存管理为5个区域,分别是程序计数器、虚拟机栈、本地方法栈、堆、方法区。其中,程序计数器、虚拟机栈中的栈帧、本地方法栈是线程独有,独立使用一块内存的。故而,它们的生命周期是和线程同步的,正所谓一定同年同月同日生,必须同年同月同日死的好兄弟啊。但是,堆和方法区,是所有线程共享使用,每个线程拥有的内存大小,都是动态的,对于它们的内存回收也是不确定的。故,GC主要是针对它们而生的。
如何判断对象是否已死?
有一个比较广泛的算法:引用计数算法。该算法描述为:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻,计数器值为0的对象,就是不可能被引用的。
像微软的COM、使用ActionScript3的FlashPlayer、Python等都是用这个算法。但是,Java是使用这个算法吗?
用如下这段代码,可以说明
/**
* 运行这段程序,需要在运行设置的VM Arguments中写入如下语句
* -verbose:gc
* 它的作用是在控制台输出GC的详细信息。
* @author qianl
*
*/
public class Test {
public Object instance = null;
private static final int _1M = 1024 * 1024;
private byte[] size = new byte[2 * _1M]; //占用一点内存,以便在GC日志中观察是否被回收过
public static void main(String[] args) {
// TODO Auto-generated method stub
Test t1 = new Test();
Test t2 = new Test();
t1.instance = t2; //t2对象被引用,如果Java使用引用计数算法,那么其值+1
t2.instance = t1; //t1对象被引用,如果Java使用引用计数算法,那么其值+1
t1 = null; //t1为null,它的成员变量instance所引用的对象将不会被用到。
t2 = null; //t2为null,它的成员变量instance所引用的对象将不会被用到。
/**
* 在此使用Java的垃圾回收,由上面代码可知,t1和t2两个对象将不可能被用到,但是他们的引用计数的值
* 却不为0,它们会被回收吗?
*/
System.gc();
}
}
它的运行结果为:
[
GC 4408K->144K(59648K), 0.0011230 secs]
[Full GC 144K->116K(59648K), 0.0053720 secs]
注意第一句
GC 4408K->144K,这说明,Java的GC,将对象回收了的。由此,可以说明,Java的GC机制,不是使用引用计数算法的。
那,JavaGC使用什么算法呢?
首先介绍一下,这个算法:根搜索算法,通过一系列名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(就是这个对象到GC Roots节点不可到达)时,则证明这个对象是不可到达的,就会被GC回收。
如下所示,其中Object7,Object8,Object9,就是被不可到达GC Roots的,就是GC回收的对象。
上面的内容,都涉及到一个名词:引用。那什么是引用?
通俗的解释为:一个reference类型的数据中存储的数值代表另外一块内存的起始地址,这块内存代表的就是一个引用。
其实,Java1.2以后,引用不止这么简单,有四种引用,分别为:强引用(如Object obj = new Object()),软引用、弱引用、虚引用。这里,我就抛砖引玉一下,大家想了解的可以Google或者度娘一下。(PS:因为我本人也不是很了解,呵呵)。
GC对方法区的回收是怎样判断的呢?
GC对于堆的回收,效率是比较高的,一次回收,基本上都可以回收百分之七八十的空间。而方法区,效率要低得多。
对于此部分,GC主要回收两部分:废弃常量和无用类。
废弃常量:如一个字符串“ABC”进入了常量池,但是系统中,没有一个String对象叫做“ABC”,即没有任何String对象引用它,那么,这个字符串就很可能被GC回收。常量池中的接口、方法、字段等都类似。
无用类:必须满足以下三个条件,才可能被GC回收
* 该类所有实例都已经被回收,即堆中不存在该类实例
* 加载该类的ClassLoader已经被回收
* 该类对应的java.lang.Class对象没有被任何地方引用,无法通过反射机制访问该类
分享到:
相关推荐
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代标准I/O(BIO)模型的新选择。NIO在Java 1.4版本引入,它为Java应用提供了高效、低延迟的数据处理方式,特别适合于高...
Java中的`util`类是Java开发中不可或缺的一部分,它们提供了许多数据结构和工具类的实现,使得开发者可以方便地处理各种数据。`java.util`包是Java标准库的核心部分,包含了许多用于处理集合、时间日期、随机数生成...
### 细说Java线程问题:深入理解与实践 在Java编程中,线程是执行的基本单位,它允许程序在操作系统层面并发执行多个任务。掌握Java线程的原理及其使用方法,对于提升软件性能和响应性至关重要。本文将从线程的概念...
### 细说Java之常用集合类 #### 一、引言 在Java开发过程中,我们经常需要处理数据的集合操作,比如存储、检索、排序等。为了方便开发者使用,Java SDK提供了一系列内置的集合类,它们主要位于`java.util`包中。...
最后,关于学习资源,"细说Java之常用集合类.pdf"这本书籍教程应该详细介绍了这些集合类的用法和实现细节,可以帮助开发者更好地理解和运用Java集合框架。"下载说明.txt"可能包含获取更多资源的指南,如"A5下载- 更...
韩顺平细说servlet.生成验证码的代码
《细说PHP》作为一本面向PHP应用开发新手的入门教材,覆盖了PHP语言的基础知识和应用实践。书中内容既实用又全面,这使得它非常适合那些刚接触PHP或者准备开始PHP学习的读者。 首先,初学者需要了解的是PHP的基础...
《细说PHP》开发Web应用程序PHP是最理想的工具,易于使用、功能强大、成本低廉、高安全性、开发速度快且执行灵活。 《细说PHP》以实用为目标设计,包含PHP开发最主流的各项技术,对每一个知识点都进行了深入详细的...
Servlet是Java EE(现在称为Java Platform, Enterprise Edition或 Jakarta EE)技术栈中的核心组件,主要用于构建Web应用程序。本文将深入探讨Servlet的相关知识点,包括它的背景、功能、在Java EE体系中的位置以及...
《细说Android 4.0 NDK编程 源码》这本书深入探讨了在Android平台上进行原生代码开发的关键技术和实践。NDK(Native Development Kit)是Google为开发者提供的一套工具,允许他们在Android应用中集成C和C++代码,以...
兄弟连 细说Linux PDF文档。共12个按章节总结
细说linux pdf 兄弟连(lampbrother)李明linux课程pdf
J2EE(Java 2 Platform, Enterprise Edition)是Java平台上针对企业级应用的一套标准,包含了13种技术,包括Servlet、JSP、EJB等。其中,Servlet是用于接收和响应HTTP请求的服务器端组件,而JSP则负责动态生成HTML...
《细说Android4.0NDK编程》由王家林所著,通过NDK,应用程序可以非常方便地实现Java与C/C++代码的相互沟通。本书顺应Android软/硬件、云计算整合潮流,详细剖析了NDK开发中涉及的各类问题和解决方案:搭建Android ...
总的来说,《韩顺平细说Servlet源代码》这门课程涵盖了Servlet开发的核心知识点,是Java Web开发者必备的学习资料。通过学习,你可以深入理解Servlet的工作机制,提升Web应用开发的效率和质量。同时,韩顺平的讲解...
PHP课件 细说PHP
Servlet是Java Web开发中的核心组件,它是一种服务器端的Java应用程序,主要用于处理和响应客户端(如Web浏览器)的请求。韩顺平老师的“2011细说Servlet笔记”是针对这一主题的深入讲解,旨在提供全面且实用的学习...
《细说PHP》配套源码,很罕见的案例哟 /*==================================================================*/ /* 文件名:comm_pro.php */ /* 概要: 文章评论的处理页面. ...
细说php