文档章节

Java垃圾回收与内存

郑光宗
 郑光宗
发布于 2017/05/06 11:10
字数 1687
阅读 11
收藏 1

1.垃圾回收

对象是使用new创建的, 但是并没有与之相对应的delete操作来回收对象占用的内存. 当我们完成对某个对象的使用时, 只需停止该对象的引用:
->将引用改变为指向其他对象
->将引用指向null
->从方法中返回, 使得该方法的局部变量不复存在

要点:
->当我们从任何可执行代码都无法到达某个对象时, 它所占用的空间就可以被回收.
->垃圾回收意味着我们永远不用担心出现虚悬引用(dangling reference). 虚悬引用, 指得是引用已经被删除的内存空间. 在那些程序员可以直接控制何时删除对象的系统中, 会存在这样的问题.
->垃圾回收器模型: 引用计数器法(不能解决循环引用), 标记-清除(mark-and-sweep)

2.终结

finalize方法
->在垃圾回收器确定该对象是不可达的且该对象的空间将被回收之后, 垃圾回收器就会调用这个方法.
->这个方法可以清除该对象所使用的所有非内存资源, 对每一个对象最多只能调用一次, 即使在这个方法的执行使得该对象重新变为可达之后又马上会再次变为不可达的情况下, 该方法也只能调用一次.
->finalize方法可以在任何特定的时间段内被调用, 它也可能永远不会被调用(java虚拟机结束).

覆写finalize方法
->当一个对象变成垃圾时, 它所引用的其他对象也很有可能会变成垃圾. 这些垃圾可能在调用我们编写的finalize方法之前就已经被终结了, 因此它们可能处于不可预知的状态.
->覆写finalize方法是, 加上super.finalize方法. 最好加在finally字句里面.保证其超类中声明的部分内容也可以被终结.

3.与垃圾回收器交互的相关类和方法

类: Runtime.getRuntime(), System
方法:gc(), runFinalization(), freeMemory(), totalMemory(), maxMemory()
System类支持静态的gc()和runFinalization()方法, 它们将调用当前Runtime对象上的相应方法.

4.可达性状态和引用对象
对象只有在没有任何引用指定它的时候才可以被当作垃圾回收, 但有时我们可能希望在仍旧有选定引用指向对象时, 将该对象作为垃圾回收掉.

引用对象的唯一用途就是维护对另一个被称为指称物(referent)的对象的引用. 通常我们通过字段或者局部变量来维护对对象的引用, 但是现在我们可以维护对引用对象的直接引用, 而该引用对象包装了我们实际需要的对象. 垃圾回收器可能判断出对某个对象的残留引用是否都是经由引用对象面引用到该对象的, 因此它可以决定是否要回收该对象. 引用对象的强度将决定垃圾回收器的行为, 普通的引用都是强度最大的引用.

Reference类
->包:java.lang.ref
->典型方法: get(), clear(), enqueue(), isEnqueued()

引用和可达性强度
->对象是强可达的(strongly reachable):普通的引用
->对象是软可达的(softly reachable):SoftReference
->对象是弱可达的(weakly reachable):WeakReference
->对象是虚可达的(phantom reachable):PhantomReference
->对象是不可达的:没有引用链接
一旦对象变为弱可达的(或者列弱), 它就可以被终结. 如果在终结之后该对象是不可达的, 那么它就可以被回收了.

对象可达性阶段会触发垃圾回收器对相关的引用对象类型做出适当的行为:
->软可达对象可能会任凭垃圾回收器去回收. 我们可确定的是所有对软可达对象的SoftReference都会在抛出outofMemoryError错误这前被清除.
->弱可达对象将会被垃圾回收器回收.
->虚可达对象并不是真正意义上的可达, 因为无法通过PhantomReference访问其指称对象, 其get方法总是返回null. 但是虚引用的存在可以防止对象在显式清除虚引用之前被回收. 虚引用使我们可以处理那些finalize方法已经被调用过的对象, 从而可以安全地认为它们是"死"的.

还有:Java堆的管理—垃圾回收提到一下几点,很不错,或许可以作为写程序时候的准则:
(1)不要试图去假定垃圾收集发生的时间,这一切都是未知的。
    比如,方法中的一个临时对象在方法调用完毕后就变成了无用对象,这个时候它的内存就可以被释放。 

(2)Java中提供了一些和垃圾收集打交道的类,
    而且提供了一种强行执行垃圾收集的方法--调用System.gc(),
    但这同样是个不确定的方法。Java 中并不保证每次调用该方法就一定能够启动垃圾收集,
    它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。

(3)挑选适合自己的垃圾收集器。一般来说,如果系统没有特殊和苛刻的性能要求,
    可以采用JVM的缺省选项。否则可以考虑使用有针对性的垃圾收集器,
    比如增量收集器就比较适合实时性要求较高的系统之中。
    系统具有较高的配置,有比较多的闲置资源,可以考虑使用并行标记/清除收集器。

(4)关键的也是难把握的问题是内存泄漏。
        良好的编程习惯和严谨的编程态度永远是最重要的,不要让自己的一个小错误导致内存出现大漏洞。

(5)尽早释放无用对象的引用。
    大多数程序员在使用临时变量的时候,
    都是让引用变量在退出活动域(scope)后,自动设置为null,
    暗示垃圾收集器来收集该对象,还必须注意该引用的对象是否被监听,如果有,则要去掉监听器,然后再赋空值。
    就是说,对于频繁申请内存和释放内存的操作,还是自己控制一下比较好,
    但是System.gc()的方法不一定适用,最好使用finallize强制执行或者写自己的finallize方法。

© 著作权归作者所有

郑光宗
粉丝 20
博文 117
码字总数 148900
作品 0
海淀
程序员
私信 提问
JVM系列第8讲:JVM 垃圾回收机制

在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由《Java 虚拟机规范》指定的,每个 Java 虚拟机可能都有不同的实现。其实涉及到 Java 虚拟机的内存,就不得不谈到 Ja...

陈树义
2018/11/21
0
0
Java finalize方法

《JAVA编程思想》: java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()。 (1).对象不一定会被回收。 (2).垃圾回收不是析构函数。 (3).垃圾回收只与内存有关。 (4)....

清风伴月
2017/10/22
0
0
Java GC系列:Java垃圾回收详解

Java的内存分配与回收全部由JVM垃圾回收进程自动完成。与C语言不同,Java开发者不需要自己编写代码实现垃圾回收。这是Java深受大家欢迎的众多特性之一,能够帮助程序员更好地编写Java程序。 ...

满风
2015/04/10
0
0
Java内存垃圾回收(Garbage Collection)机制基本方法和原则:System.gc()与finalize()

版权声明:本文为Zhang Phil原创文章,请不要转载! https://blog.csdn.net/zhangphil/article/details/84650786 Java内存垃圾回收(Garbage Collection)机制基本方法和原则:System.gc()与f...

zhangphil
2018/12/01
0
0
《成神之路-基础篇》JVM——垃圾回收(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收 ...

2018/05/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Redox OS 发布 0.5 版

Redox OS 是一个几乎完全以 Rust 语言编写的通用操作系统及周围生态(例如文件系统、显示服务器及 Rust 版本的 libc)。其遵循微内核架构,在一定程度上兼容于 POSIX。 该项目于日前发布了 ...

linuxCool
31分钟前
0
0
更新上传git/gitee项目时出现密码配置错误(incorrect username or password)的解决办法

1.输入【git remote add origin git地址】 命令时出现incorrect username or password的错误,这是因为之前弹出输入账户和密码时输错了,而且会一直默认错误的账户和密码,因此需要把之前输入...

west_coast
39分钟前
0
0
Jenkins基础入门-1-Jenkins简单介绍和环境安装

如果在做自动化测试的朋友,应该熟悉Jenkins,或者至少使用过。如果一个人没有使用过Jenkins或者hudson,hudson是Jenkins的前身,他还说自己做过自动化测试,只能说,他只不过是在做半自动化...

shzwork
39分钟前
0
0
linux上解压版安装jdk,tomcat

需要的安装包 1.vmware12 2.centos7版本 3.安装完成后需要xshell来连接远程虚拟机,虚拟机保证要联网,网络畅通。 4.xftp用来向linux传输文件用,一般来说xshell和xftp配套使用 5.对应的压缩...

architect刘源源
今天
26
0
使用 spring 的 IOC 解决程序耦合

工厂模式解耦 在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时...

骚年锦时
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部