Java垃圾回收器工作原理

简介:

垃圾回收器是如何工作的?我现在就简单的介绍一下

首先要明确几点:

Java是在堆上为对象分配空间的

垃圾回收器只跟内存有关,什么IO啊,网络连接啊,管它P事

当可用内存数量较低时,Sun版本的垃圾回收器才会被激活

在垃圾回收器回收垃圾之前,我们先来了解一下Java分配对象的方式,Java的堆更像一个传送带,每分配一个新对象,它就往前移动一格。这意味着对象存储空间的分配速度相当快。Java的“堆指针”只是简单地移动到尚未分配的领域。也就是说,分配空间的时候,“堆指针”只管依次往前移动而不管后面的对象是否还要被释放掉。如果可用内存耗尽之前程序就退出就再好不过了,这样的话垃圾回收器压根就不会被激活。

但是由于“堆指针”只管依次往前移动,那么你肯定会想,总有一天内存会被耗尽,垃圾回收器就开始释放内存。这里有人肯定会问:怎么判断某个对象该被回收呢?答案就是当堆栈或静态存储区没有对这个对象的引用时,就表示程序(员)对这个对象没有兴趣了,它就应该被回收了。有两种方法来知道这个对象有没有被引用:第一种是遍历堆上的对象找引用;第二种是遍历堆栈或静态存储区的引用找对象。前者的实现叫做“引用计数法”,意思就是当有引用连接至对象时,引用计数加1,当引用离开作用域或被置为null时,引用计数减1,这种方法有个缺陷,如果对象之间存在循环引用,可能会出现“对象应该被回收,但引用计数却不为零”的情况。

Java采用的是后者,在这种方式下,Java虚拟机采用一种“自适应”的垃圾回收技术,如何处理找到的存活对象(也就是说不是垃圾),Java有两种方式:

一种是“停止-复制”:理论上是先暂停程序的运行(所以它不属于后台回收模式),然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全是垃圾。当对象被复制到新堆上时,它们是一个挨着一个的,所以新堆保持紧凑排列(这也是为什么分配对象的时候“堆指针”只管依次往前移动)。然后就可以按前述方法简单、直接地分配内存了。这将导致大量内存复制行为,内存分配是以较大的“块”为单位的。有了块之后,垃圾回收器就可以不往堆里拷贝对象了,直接就可以往废弃的块里拷贝对象了。

另一种是“标记-清扫”:它的思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。每当它找到一个存活对象,就会给对象一个标记。这个过程中不会回收任何对象。只有全部标记完成时,没有标记的对象将被释放,不会发生任何复制工作,所以剩下的堆空间是不连续的,然后垃圾回收器重新整理剩余的对象,使它们是连续排列的。

当垃圾回收器第一次启动时,它执行的是“停止-复制”,因为这个时刻内存有太多的垃圾。然后Java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到“标记-清扫”方式;同样,Java虚拟机会跟踪“标记-清扫”效果,要是堆空间出现很多碎片,就会切换到“停止-复制”方式。这就是所谓的“自适应”技术。

其实仔细想一下,“停止-复制”和“标记-清扫”无非就是:“在大量的垃圾中找干净的东西和在大量干净的东西里找垃圾”。不同的环境用不同的方式,这样做完全是为了提高效率,要知道,无论哪种方式,Java都会先暂停程序的运行,所以,垃圾回收器的效率其实是很低的。Java用效率换回了C++没有的垃圾回收器和运行时的灵活,我认为这是明智的选择(虽然它只跟内存有关),随着硬件的飞速发展,我相信,开发时间要比运行效率重要得多!

引用:http://fhz1980.blog.163.com/blog/

本文转自天天_byconan博客园博客,原文链接:http://www.cnblogs.com/tiantianbyconan/archive/2013/01/07/2848878.html ,如需转载请自行联系原作者
相关文章
|
存储 缓存 Java
我们来详细讲一讲 Java NIO 底层原理
我是小假 期待与你的下一次相遇 ~
484 2
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
413 0
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
432 0
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
971 58
|
人工智能 安全 Java
Go与Java泛型原理简介
本文介绍了Go与Java泛型的实现原理。Go通过单态化为不同类型生成函数副本,提升运行效率;而Java则采用类型擦除,将泛型转为Object类型处理,保持兼容性但牺牲部分类型安全。两种机制各有优劣,适用于不同场景。
716 24
|
XML JSON Java
Java 反射:从原理到实战的全面解析与应用指南
本文深度解析Java反射机制,从原理到实战应用全覆盖。首先讲解反射的概念与核心原理,包括类加载过程和`Class`对象的作用;接着详细分析反射的核心API用法,如`Class`、`Constructor`、`Method`和`Field`的操作方法;最后通过动态代理和注解驱动配置解析等实战场景,帮助读者掌握反射技术的实际应用。内容翔实,适合希望深入理解Java反射机制的开发者。
1105 13
|
算法 Java 索引
说一说 Java 并发队列原理剖析
我是小假 期待与你的下一次相遇 ~
185 1
|
安全 Java 编译器
JD-GUI,java反编译工具及原理: JavaDecompiler一个Java反编译器
Java Decompiler (JD-GUI) 是一款由 Pavel Kouznetsov 开发的图形化 Java 反编译工具,支持 Windows、Linux 和 Mac Os。它能将 `.class` 文件反编译为 Java 源代码,支持多文件标签浏览、高亮显示,并兼容 Java 5 及以上版本。JD-GUI 支持对整个 Jar 文件进行反编译,可跳转源码,适用于多种 JDK 和编译器。其原理基于将字节码转换为抽象语法树 (AST),再通过反编译生成代码。尽管程序可能带来安全风险,但可通过代码混淆降低可读性。最新版修复了多项识别错误并优化了内存管理。
11316 1
|
存储 算法 Java
G1原理—5.G1垃圾回收过程之Mixed GC
本文介绍了G1的Mixed GC垃圾回收过程,包括并发标记算法详解、三色标记法如何解决错标漏标问题、SATB如何解决错标漏标问题、Mixed GC的过程、选择CollectSet的算法
G1原理—5.G1垃圾回收过程之Mixed GC