本系列博客旨在帮助大家理解java垃圾收集器及其工作原理,这是系列的第二篇。


java垃圾回收事实上是由一个能够进行自己主动内存管理的进程完毕的,这使得程序猿在写代码的时候不必过多考虑内存释放与回收的问题。



垃圾收集器怎样初始化:
作为一个自己主动化的进程,程序猿并不须要显式地在代码中初始化垃圾收集进程。所谓的System.gc()和Runtime.gc()都属于请求JVM初始化垃圾收集进程的钩子函数。虽然这样的请求机制为程序猿提供了一个初始化该进程的机会,可是实际上控制权仍掌握在JVM手中。也就是说JVM可以选择忽略程序猿的请求。因而不要指望虚拟机可以足够听话。其实,它总是基于堆内存Eden区域的内存分配情况来作出推断。而详细的推断方式虚拟机规范上并没有强制要求,这个因不同虚拟机实现而异。

垃圾收集进程:

垃圾收集就是一个回收无用空间使之将来能够又一次分配给其它对象用的进程。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="font-size:13.63636302947998px">

Eden区域:当实例被创建,优先存储在新生代的Eden区域。


Survivor区域(S0和S1):作为Minor GC(新生代GC)生命周期的一个步骤。Eden区域中的存活对象将会被移到S0区域。而S0区域中的存活对象在被GC扫描之后将会被移到S1区域。

而死亡对象将会被GC标记。

被标记的对象可能会在标记后由此进程去回收也可能由一个单独的进程去回收(有四种类型的垃圾收集器,下篇我们将会学习)。

老年代:老年代是堆内存的还有一个逻辑组成部分。gc运行完MinorGC之后,某些在S1区域中依然存活的对象
将会晋升到老年代(译者注:并非全部对象都可以晋升,仅仅有熬过若干次MinorGC的对象才干晋升。这里有个对象年龄的概念,详细可參见专栏其它文章),而无用对象将会被标记。

MajorGC:MajorGC事实上就是老年代GC,在此期间,垃圾收集进程会扫描老年代中全部对象,标记死亡对象,被标记的对象随后将会被回收而其它对象依然存活。

内存碎片:当被标记的对象被清除后。堆内存会出现一些“空洞”,即内存碎片。

为了提高对象分配的速度,我们应该清除掉这些内存碎片。当然,这取决于详细的gc回收器实现。



实例的终结:
对象实例被回收之前,垃圾收集器可能会调用其finalize方法。因而对象能够在此方法中进行一些资源释放的操作(译者注:没有复写finalize方法的对象似乎并不须要运行其父类的finalize方法,參考《深入理解java虚拟机 JVM高级特性与最佳实践》3.2.4节),虽然finalize方法在该对象被回收前是一定会被运行的,可是确并没有一个明白的时间和明白的顺序,多个待回收的实例调用finalize方法的先后顺序不能够被设置,它们甚至会并行的运行。(译者注:这里说的运行finalize方法只指触发这种方法,但虚拟机不承诺等待其运行结束,由于假设finalize方法运行时间过长,将会影响其它对象的回收,甚至导致整个内存回收系统崩溃

1.假设在回收一个垃圾对象的过程中出现异常,默认将会被忽略,而且取消回收该对象实例。

2.虚拟机规范并没有对虚引用的垃圾回收过程进行强制规定。细节由虚拟机实现者决定。
3.垃圾回收过程是由一个守护线程运行的。


对象何时能回收:
1.一个线程訪问不到该对象实例;
2.该对象(或者是若干对象循环引用)不被不论什么其它对象所引用。
(译者注:上面定义不是非常直观,事实上这里有个根引用算法以及GC root的概念,详细參见专栏其它文章)

java中有不同的引用类型,垃圾回收因引用类型而异。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

在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在声明lion之后,所以在main方法的输出之前。finalize方法就已经输出“rest in Peace!”了,当然了。我们并不能保证输出这种结果,由于这取决于虚拟机实现以及内存使用情况。
(译者注:假设没有运行垃圾回收,则上述代码并不会调用finalize方法)可是我们学到一点。那就是编译器能够选择提前释放一个对象实例假设其预见到该对象将来不会被使用。

描写叙述GC范围的演示样例代码:

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++;
}
GC OutOfMemoryError演示样例:
java世界也会有内存溢出问题。

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)

下篇我们将介绍不同的垃圾收集器类型。

原文:http://javapapers.com/java/how-java-garbage-collection-works/

GC入门指南(二)------GC工作原理的更多相关文章

  1. 【SpringMVC架构】SpringMVC入门实例,解析工作原理(二)

    上篇博文,我们简单的介绍了什么是SpringMVC.这篇博文.我们搭建一个简单SpringMVC的环境,使用非注解形式实现一个HelloWorld实例,从简单入手,逐步深入. 环境准备 我们须要有主要 ...

  2. Struts2(二):工作原理

    struts可查看源码:https://github.com/apache/struts 在学习struts2之前,我先看了一些比较早版本对struts2的工作原理相关的介绍,顺便抄写过来,用来帮助自 ...

  3. require.js入门指南(二)

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  4. kotlin 语言入门指南(二)--代码风格

    语言风格 这里整理了 kotlin 惯用的代码风格,如果你有喜爱的代码风格,可以在 github 上给 kotlin 提 pull request . 创建DTOs(POJSs/POCOs) 文件: ...

  5. 《转载》编程入门指南 v1.4

    编程入门指南 v1.4 Badger · 8 个月前 作者:@萧井陌, @Badger 自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 CoCode ...

  6. zabbix监控的基础概念、工作原理及架构

    一.什么是zabbix及优缺点(对比cacti和nagios) Zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题.是一个基于WE ...

  7. MapReduce 1工作原理图文详解

    MapReduce工作原理图文详解 一 MapReduce程序执行流程 程序执行流程图如下: 流程分析:1.在客户端启动一个作业.2.向JobTracker请求一个Job ID.3.将运行作业所需要的 ...

  8. Java中GC的工作原理

    转文: 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能提高整个 ...

  9. JVM 的 工作原理,层次结构 以及 GC工作原理

    JVM Java 虚拟机 Java 虚拟机(Java virtual machine,JVM)是运行 Java 程序必不可少的机制.JVM实现了Java语言最重要的特征:即平台无关性.原理:编译后的 ...

随机推荐

  1. shell特殊符号用法大全

      # 注释符号(Hashmark[Comments]) 1.在shell文件的行首,作为shebang标记,#!/bin/bash; 2. 其他地方作为注释使用,在一行中,#后面的内容并不会被执行, ...

  2. Sprak RDD简单应用

    来自:http://my.oschina.net/scipio/blog/284957#OSC_h5_11 目录[-] 1.准备文件 2.加载文件 3.显示一行 4.函数运用 (1)map (2)co ...

  3. 深入Java数据类型

    Java的数据类型分为两大类,一类是基本数据类型,还有一类就是引用数据类型. 1.基本数据类型 Java一共有8种基本数据类型,分别是byte,short,int,long,float,double, ...

  4. fiddle-获取 Cookie 信息

    随着网络安全(例如:登录安全等)要求的不断提升,越来越多的登录应用在登录时添加了验证码登录,而验证码生成算法也在不断的进化,因而对含登录态的自动化测试脚本运行造成了一定程度的困扰,目前解决此种问题的方 ...

  5. Single Number II - LeetCode

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  6. 转:Maven项目中获取classpath和资源文件的路径

    假设资源文件放在maven工程的 src/main/resources 资源文件夹下,源码文件放在 src/main/java/下, 那么java文件夹和resources文件夹在运行时就是class ...

  7. Jenkins连接git时出现“Failed to connect to repository : Command ... HEAD" returned status code 128:”的问题解决

    网上说的解决方法如下: 其实生成ssh时不应该使用当前用户去生成ssh,而是使用jenkins这个用户去生成ssh,然后再去git服务器上配置你生成key,最后再jenkins上配置返回给你的key. ...

  8. ios修改hosts文件后访问网址114导航域名无法解析问题

    当前的问题是打开hosts文件转换成utf8格式浏览发现前面有@之类的非法字符,手动修改后可以访问.

  9. 误删docker0网桥之后怎么办呢?

    今天,在搭建k8s node节点环境的时候,好巧不巧,执行了如下命令: [root@hxin221 ~]# ifconfig docker0 down &>/dev/null [root ...

  10. 安全 --- CSRF攻击

    什么是CSRF CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/X ...