[译]Java垃圾回收是如何工作的
说明:这篇文章来翻译来自于Javapapers 的How Java Garbage Collection Works
这部分教程是为了理解Java垃圾回收的基础以及它是如何工作的。这是垃圾回收系列教程的第二部分。希望你已经读过第一部分的Java垃圾回收介绍。
Java垃圾回收是一个用来管理程序运行时内存的自动的进程。因为它是JVM自动来处理的,所以它将程序员从程序的内存资源的分配和释放中解放出来。
Java垃圾回收 GC开启##
作为一个自动的进程,程序员不需要在代码中显示的去启动垃圾回收进程。System.gc()和Runtime.gc()用来提供向JVM发出请求去开启垃圾回收进程。
尽管这个请求机制给程序员提供了一个机会去开启进程,但是主动权还是在JVM中。它可以选择区拒绝这个请求而且它也不保证这些调用会做垃圾回收工作。这个决定是由JVM根据在堆内存中的Eden区是否可用做出来的。JVM规范把这个留给了具体的实现,所以具体的实现还需要看实现规范说明。
毫无疑问我们知道垃圾回收经常不能够被强迫的。我偶尔发现一种场景就是当在调用System.gc()时起作用了。通过这篇文章(System.gc() invocation is applicable)我们可以了解这个难以发现的实例。
垃圾回收进程##
垃圾回收是一个释放无用的内存区并且使它能够被将来的实例能够使用的一个进程。
![]()
Eden Sapce:当实例被创建的时候,它首先被存放到堆内存中的年轻代的Eden区。
说明:如果你不理解这些名词,我建议你去浏览垃圾回收介绍教程,这里面详细的介绍了内存模型、JVM结构还有这些名词。
Surivor Space(S0 and S1):作为minor垃圾回收的一部分,仍然存活的对象(仍然被引用着)从Eden 区移动到survivor 区S0.于此类似的是垃圾回收器扫描S0并且把存活的实例移到S1。
不再存活(没有引用)的实例被垃圾回收器打上标记。和垃圾回收器有关,是否选择标记实例是在运行的时候从内存中移除还是在在不同的进程中由垃圾回收进行来做。
Old Generation:老年代是堆内存的第二个逻辑部分。当垃圾回收器在进行minor GC时候,在S1中仍然仍然存活的会被移动老年代中。在S1中不再被引用的将被标记回收。
Major GC:相对于垃圾回收进程,老年代是实例生命周期的最后一步。Major GC是垃圾回收进程中扫描堆内存中来年代部分的。如果实例不再被引用,然后他们会被标记回收而如果还仍然被引用着他们将继续留在老年代中。
Memory Fragmentation(内存碎片):一旦实例从堆内存被删除以后,它所在的区域就变成了工而且能够被将来存活的实例所使用。这些空的区域在整个内存区域将以碎片的形式存在。对于更快地分配实例这些应该得到整理。决定于垃圾回收器的选择,被释放的内存区是在运行的时候被压缩还是在处理完成之后再处理。
在垃圾回收中的实例初始化##
在回收实例和释放内存空间之前,垃圾回收器会调用finalize()方法以便实例能够有机会释放它所拥有的任何资源。尽管finalize()方法在释放内存空间之前肯定会被调用,但是这个没有顺利和时间要求指出来。在多个实例之间的顺序是不能够提前决定的,因为他们可能并行的发生。程序不应该在调用finalize()的时候不应该指定它在实例和释放资源的顺序。
- 在清理进程中任何抛出的未被捕获的异常都将会忽略并且这个实例的清理过程或被取消。
- JVM规范没有讨论关于弱引用的垃圾回收也没有明显的指明,它把详细的实现留给了JVM的实现者。
- 垃圾回收是通过守护线程来做的。
什么时候一个对象能够被垃圾回收?##
- 任何一个实例都不能被一个存活的线程所访问的时候
- 有争议的被引用的实例不能够被任何其他的实例所访问的时候
有Java中有不同种类的引用。能否被垃圾回收取决于它所拥有的引用类型
| Reference | Garbage Collection |
| Strong Reference | Not eligible for garbage collection |
| Soft Reference | Garbage collection possible but will be done as a last option |
| Weak Reference | Eligible for Garbage Collection |
| Phantom Reference | Eligible for Garbage Collection |
在编译过程中,作为一种优化技术Java编译器能够选择将null值分配给一个实例,以便这个实例能够被标记回收。
class Animal {
public static void main(String[] args) {
Animal lion = new Animal();
System.out.println("Main is completed.");
}
protected void finalize() {
System.out.println("Rest in Peace!");
}
}
在上面这个类中,lion实例在实例化行从来没有被使用。所以Java编译器作为优化的策略可以将赋值lion=null实例化所在行。所以,尽管在SOP's输出之前,初始化器可能打印出Reset in Peace!。我们不能确切的表明它,因为它依赖与JVM具体的实现以及在运行时的内存使用。但是能够获悉的是,如果编译器能够察觉它在将来不会被引用了它可以在程序中选择去释放这些实例。
- 再来讲一个很棒的例子关于一个实例能够被垃圾回收所控制的时候。实例的所有属性能够存储在寄存器中,然后寄存器能够访问到这些值。尽管这些值有可能被将来使用,但是这个实例可以被标记为能够被垃圾回收器控制,很经典吧??难道不是吗?
- 可以将可能简单的将一个实例设置为能够被垃圾回收器控制当null被分配给它的时候或者它像上面说那样复杂的时候。这些选择都可以由JVM实现来决定。目标就是尽可能小的去干扰它,提升响应增加产出。为了取到这个目标,JVM的实现可以选择一个更好的模式或者算法在垃圾回收时进行内存回收。
- 当
finalize()方法被调用的时候,JVM会释放在这个线程中的同步锁。
垃圾回收作用域的示例程序
Class GCScope {
GCScope t;
static int i = 1;
public static void main(String args[]) {
GCScope t1 = new GCScope();
GCScope t2 = new GCScope();
GCScope t3 = new GCScope();
// No Object Is Eligible for GC
t1.t = t2; // No Object Is Eligible for GC
t2.t = t3; // No Object Is Eligible for GC
t3.t = t1; // No Object Is Eligible for GC
t1 = null;
// No Object Is Eligible for GC (t3.t still has a reference to t1)
t2 = null;
// No Object Is Eligible for GC (t3.t.t still has a reference to t2)
t3 = null;
// All the 3 Object Is Eligible for GC (None of them have a reference.
// only the variable t of the objects are referring each other in a
// rounded fashion forming the Island of objects with out any external
// reference)
}
protected void finalize() {
System.out.println("Garbage collected from object" + i);
i++;
}
Example Program for GC OutOfMemoryError
Garbage collection does not guarantee safety from out of memory issues. Mindless code will lead us to OutOfMemoryError.
import java.util.LinkedList;
import java.util.List;
public class GC {
public static void main(String[] main) {
List l = new LinkedList();
// Enter infinite loop which will add a String to the list: l on each
// iteration.
do {
l.add(new String("Hello, World"));
} while (true);
}
}
输出:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.LinkedList.linkLast(LinkedList.java:142)
at java.util.LinkedList.add(LinkedList.java:338)
at com.javapapers.java.GCScope.main(GCScope.java:12)
[译]Java垃圾回收是如何工作的的更多相关文章
- [译]Java 垃圾回收介绍
说明:这篇文章来翻译来自于Javapapers 的Java Garbage Collection Introduction 在Java中,对象内存空间的分配与回收是由JVM中的垃圾回收进程自动完成的. ...
- Java垃圾回收机制的工作原理
Java垃圾回收机制的工作原理 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 获取更多内容,请关注小编个人微信公众平台: 一.Java中引入垃圾回收机制的作用 ...
- Java GC系列(2):Java垃圾回收是如何工作的?
本文由 ImportNew - 伍翀 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 本教程是为了理解基本的Java垃圾回收以及它是如何 ...
- Java垃圾回收是如何工作的?
本教程是为了理解基本的Java垃圾回收以及它是如何工作的.这是垃圾回收教程系列的第二部分.希望你已经读过了第一部分:<Java 垃圾回收介绍>. Java 垃圾回收是一项自动化的过程,用来 ...
- [译]Java 垃圾回收的监控和分析
说明:这篇文章来翻译来自于Javapapers 的Java Garbage Collection Monitoring and Analysi 在这个系列的Java垃圾回收教程中,我们将看到可用于垃圾 ...
- Java GC机制简要总结(Java垃圾回收的基本工作原理)
第一次编辑 2019-05-07 01:09:39 垃圾回收的对象 程序中的不可用对象(不存活的对象,没有任何引用),或者无用的变量信息等,在程序中长期存在会逐渐占用较多的内存空间,导致没有足够的空间 ...
- Java GC系列(1):Java垃圾回收简介
本文由 ImportNew - 好好先生 翻译自 javapapers. Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Ja ...
- Java 垃圾回收(GC) 泛读
Java 垃圾回收(GC) 泛读 文章地址:https://segmentfault.com/a/1190000008922319 0. 序言 带着问题去看待 垃圾回收(GC) 会比较好,一般来说主要 ...
- Java垃圾回收机制分析
Java的堆是一个运行时数据区,类的实例从中分配空间,堆中存储着正在运行的应用程序所建立的所有对象.垃圾回收是一种动态存储管理技术.它按照特定的垃圾回收算法,自动释放掉不再被引用的对象.堆内存里垃圾的 ...
随机推荐
- CSS不常见问题汇总
写css有一段时间了,其间也遇到一些问题,跟大家分享一下 IE10+滚动条自动以藏问题,导致滚动部分页面看起来不正常 html, body {-ms-overflow-style: scrollbar ...
- js 网上见到的动画函数 备份
<script> function startMove(obj,json,fn){ clearInterval(obj.timer); obj.timer = setInterval(fu ...
- JBPM4实例教程
JBPM语言概述:全名 Java Business Process Management ,它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源的.灵活的.易扩展的可运行流程语言框架. 是开源 ...
- 工厂模式IDAL具体解释
IDAL 一. IDAL主要功能: 1.这全然是"工厂模式"的一部分实现而已 2.这是一组接口类,当中包含了每一个要公开的数据訪问方法.为每一个数据库产品单独编写的DAL(数据訪问 ...
- Spring相框:AOP详细说明
AOP中国的名字叫做面向方面编程.这个名字是很形象.因为你真的可以把像面包切系统.并直接增加面包的修改.科而异,对整个系统,小到一定的方法. AOP它有什么用?有关示例,各组分可以含有安全.事务.,A ...
- IntelliJ Idea中一个编译报错引发的
package verify; public class Verifier { private String name; public Verifier() { this.name = getClas ...
- async和await关键字实现异步编程
async和await关键字实现异步编程 异步编程 概念 异步编程核心为异步操作,该操作一旦启动将在一段时间内完成.所谓异步,关键是实现了两点:(1)正在执行的此操作,不会阻塞原来的线程(2)一旦 ...
- 第一次测试HTML和CSS
1.HTML(Hyper Text Markup Languange)超文本标记语言.HTML文件扩展名通常是:htm和html. <html> <head> <titl ...
- 向西项目管理工具Maven一片
前言 相信仅仅要做过 Java 开发的童鞋们,对 Ant 想必都不陌生,我们往往使用 Ant 来构建项目,尤其是涉及到特别繁杂的工作量.一个 build.xml 可以完毕编译.測试.打包.部署等非常多 ...
- linux_操作基本语句
总结一下常用的和不常用的linux命令,有些命令不常用的,是要反复去看才能记住的. 1.最基础的ls命令,相当于win下的dir命令,常用参数有 -a,-l 2.cd命令,cd到一个目录,跟win下的 ...