[译]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的堆是一个运行时数据区,类的实例从中分配空间,堆中存储着正在运行的应用程序所建立的所有对象.垃圾回收是一种动态存储管理技术.它按照特定的垃圾回收算法,自动释放掉不再被引用的对象.堆内存里垃圾的 ...
随机推荐
- [python]自问自答:python -m参数? (转)
python -m xxx.py 作用是:把xxx.py文件当做模块启动但是我一直不明白当做模块启动到底有什么用.python xxx.py和python -m xxx.py有什么区别! 自问自答: ...
- 设计模式之空对象(Null Object)模式
通过引用Null Object,用于取消业务逻辑中对对象的为空推断 类图: Nullable: package com.demo.user; public interface Nullable { b ...
- APP漏洞导致移动支付隐患重重,未来之路怎样走?
没有一种支付是100%安全的,互联网及移动支付规模的增长,其交易的安全性须要银行.支付公司.App开发人员.用户等參与各方更加重视.当下手机支付似乎变成了一种时尚,用户们"刷手机" ...
- JavaEE(19) - Web层和EJB的整合(Session Bean)
1. 通过依赖注入访问无状态Session Bean #1. EJB注入Servlet中 #2. EJB注入JSF中 2. 通过EJB引用访问有状态Session Bean 3. 在工具类中访问Ses ...
- Java虚拟机参数设置(转)
今天在加载一幅图片时,eclipse报出如下错误: “Exception in thread "main" java.lang.OutOfMemoryError: Java hea ...
- Java一些八卦集合类
Map 和 Set关系 Map和Set事实基础的朋友,有着千丝万缕的联系. Map它可以被看作是Set延期.从何时起Set内容存储在key-value的值当表单.这个Set实际上可以作为Map使用.反 ...
- 【日报C在23】堆和栈的深入了解
每日一C之堆与栈的深入理解 每天拾一个C语言贝壳,厚积薄发,积跬步以致千里. 今日贝壳:内存中堆与栈的深入理解.认识一个清晰地内存 假 ...
- Sonar相关汇总
http://www.sonarqube.org/downloads/ http://docs.sonarqube.org/display/SONAR/Documentation/ 公司前段时间推动项 ...
- 模拟linux下的ls -l命令
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h&g ...
- SAE+Java+jetty
SAE的java执行环境jetty如servlet该容器,和开放几乎完全访问.有效支持各种jar包.但对于jdk的要件的版本号是非常严格格,这里的版本号是jdk1.6 SAE利用上传war该方式配置j ...