Android垃圾回收机制及程序优化System.gc_Android

1.垃圾收集算法的核心思想

  Java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。

  垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能,因此需要开发人员做比较深入的了解。

2.触发主GC(Garbage Collector)的条件

  JVM进行次GC的频率很高,但因为这种GC占用时间极短,所以对系统产生的影响不大。更值得关注的是主GC的触发条件,因为它对系统影响很明显。总的来说,有两个条件会触发主GC:
  ①当应用程序空闲时,即没有应用线程在运行时,GC会被调用。因为GC在优先级最低的线程中进行,所以当应用忙时,GC线程就不会被调用,但以下条件除外。

  ②Java堆内存不足时,GC会被调用。当应用线程在运行,并在运行过程中创建新对象,若这时内存空间不足,JVM就会强制地调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法满足要求,则 JVM将报“out of memory”的错误,Java应用将停止。

  由于是否进行主GC由JVM根据系统环境决定,而系统环境在不断的变化当中,所以主GC的运行具有不确定性,无法预计它何时必然出现,但可以确定的是对一个长期运行的应用来说,其主GC是反复进行的。

3.减少GC开销的措施

  根据上述GC的机制,程序的运行会直接影响系统环境的变化,从而影响GC的触发。若不针对GC的特点进行设计和编码,就会出现内存驻留等一系列负面影响。为了避免这些影响,基本的原则就是尽可能地减少垃圾和减少GC过程中的开销。具体措施包括以下几个方面:

  (1)不要显式调用System.gc()

  此函数建议JVM进行主GC,虽然只是建议而非一定,但很多情况下它会触发主GC,从而增加主GC的频率,也即增加了间歇性停顿的次数。

  (2)尽量减少临时对象的使用

  临时对象在跳出函数调用后,会成为垃圾,少用临时变量就相当于减少了垃圾的产生,从而延长了出现上述第二个触发条件出现的时间,减少了主GC的机会。

  (3)对象不用时最好显式置为Null

  一般而言,为Null的对象都会被作为垃圾处理,所以将不用的对象显式地设为Null,有利于GC收集器判定垃圾,从而提高了GC的效率。

  (4)尽量使用StringBuffer,而不用String来累加字符串(详见blog另一篇文章JAVA中String与StringBuffer)

  由于String是固定长的字符串对象,累加String对象时,并非在一个String对象中扩增,而是重新创建新的String对象,如 Str5=Str1+Str2+Str3+Str4,这条语句执行过程中会产生多个垃圾对象,因为对次作“+”操作时都必须创建新的String对象,但这些过渡对象对系统来说是没有实际意义的,只会增加更多的垃圾。避免这种情况可以改用StringBuffer来累加字符串,因StringBuffer 是可变长的,它在原有基础上进行扩增,不会产生中间对象。

  (5)能用基本类型如Int,Long,就不用Integer,Long对象

  基本类型变量占用的内存资源比相应对象占用的少得多,如果没有必要,最好使用基本变量。

  (6)尽量少用静态对象变量

  静态变量属于全局变量,不会被GC回收,它们会一直占用内存。

  (7)分散对象创建或删除的时间

  集中在短时间内大量创建新对象,特别是大对象,会导致突然需要大量内存,JVM在面临这种情况时,只能进行主GC,以回收内存或整合内存碎片, 从而增加主GC的频率。集中删除对象,道理也是一样的。它使得突然出现了大量的垃圾对象,空闲空间必然减少,从而大大增加了下一次创建新对象时强制主GC 的机会。

-------------------------------------------------------------

很多人把Java的“效率低下”归咎于不能自由管理内存,但我们也知道将内存管理封装起来的好处,这里就不赘述。

Java中的内存分配是随着new一个新的对象来实现的,这个很简单,而且也还是有一些可以“改进”内存回收的机制的,其中最显眼的就是这个System.gc()函数。

乍一看这个函数似乎是可以进行垃圾回收的,可事实并不是那么简单。

其实这个gc()函数的作用只是提醒虚拟机:程序员希望进行一次垃圾回收。但是它不能保证垃圾回收一定会进行,而且具体什么时候进行是取决于具体的虚拟机的,不同的虚拟机有不同的对策。

那么下一个问题就是:gc()进行回收的准则是什么?也就是说什么样的对象可以被回收?

简单来说就是:没有被任何可达变量指向的对象。这里的可达是我发明的……意思就是能够找到的,那什么样的是不可达的呢?

比如说:

a.v = b;
b.v = c;
/*
*Watch out !
*/
a.v = d;

看一下这段代码:

第一行:对象a的变量v指向了对象b
第二行:对象b的变量v指向了对象c
第六行:对象a的变量v指向了变量d。

这个时候,虽然变量c指向的对象有c 以及b.v指向它,但是它们都已经不可达了,为什么?因为唯一可以找到它们的是a.v,但是现在a.v指向了d,所以他们就是不可达的了。
理由也很直观:没有任何可达变量指向你,你还有活下去的理由吗?你就算活下去谁能找得到你呢?

所以说,C++中将释放了的指针置为null的习惯要保留到Java中,因为这有可能是你释放内存的唯一途径。

最后的箴言:不要频繁使用gc函数。

最后给大家说下为什么需要GC

应用程序对资源操作,通常简单分为以下几个步骤:

1、为对应的资源分配内存

2、初始化内存

3、使用资源

4、清理资源

5、释放内存

应用程序对资源(内存使用)管理的方式,常见的一般有如下几种:

1、手动管理:C,C++

2、计数管理:COM

3、自动管理:.NET,Java,PHP,GO…

但是,手动管理和计数管理的复杂性很容易产生以下典型问题:

1.程序员忘记去释放内存

2.应用程序访问已经释放的内存

产生的后果很严重,常见的如内存泄露、数据内容乱码,而且大部分时候,程序的行为会变得怪异而不可预测,还有Access Violation等。

.NET、Java等给出的解决方案,就是通过自动垃圾回收机制GC进行内存管理。这样,问题1自然得到解决,问题2也没有存在的基础。

总结:无法自动化的内存管理方式极容易产生bug,影响系统稳定性,尤其是线上多服务器的集群环境,程序出现执行时bug必须定位到某台服务器然后dump内存再分析bug所在,极其打击开发人员编程积极性,而且源源不断的类似bug让人厌恶。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索gc回收机制
android_gc机制
java gc回收机制、gc垃圾回收机制、c gc回收机制、gc回收机制、gc垃圾回收机制原理,以便于您获取更多的相关知识。

时间: 2024-09-19 10:04:21

Android垃圾回收机制及程序优化System.gc_Android的相关文章

Android垃圾回收机制解决内存泄露问题_Android

在android编码中,会有一些简便的写法和编码习惯,会导致我们的代码有很多内存泄露的问题,在这里做一个已知错误的总结:1.编写单例的时候常出现的错误. 错误方式: public class Foo{ private static Foo foo; private Context mContext; private Foo(Context mContext){ this.mContext = mContext; } // 普通单例,非线程安全 public static Foo getInsta

Android垃圾回收机制解决内存泄露问题

在android编码中,会有一些简便的写法和编码习惯,会导致我们的代码有很多内存泄露的问题,在这里做一个已知错误的总结: 1.编写单例的时候常出现的错误. 错误方式: public class Foo{ private static Foo foo; private Context mContext; private Foo(Context mContext){ this.mContext = mContext; } // 普通单例,非线程安全 public static Foo getInst

【转载】关于垃圾回收机制

转载自[雨声论坛]原作:software_young ----------------------转载开始------------------------所谓垃圾回收机制,指的是内存和各种变量或者目标所使用内存的释放和回收机制. 软件的发展历史,就是软件不断庞大.人力逐渐难以控制和对开发人员的技术要求逐渐降低的历史. 早先的许多软件,都是用汇编语言写的,汇编是机器码的助记符方式,因此,用汇编编程,实际就是用机器码编程.它要求程序员对机器非常熟悉才行,否则很难编出能用的程序. 那时候的程序员首先要

.Net 垃圾回收机制原理(一)

英文原文:Jeffrey Richter 编译:赵玉开 链接:http://www.cnblogs.com/yukaizhao/archive/2011/11/23/dot_net_GC_1.html 有了Microsoft.Net clr中的垃圾回收机制程序员不需要再关注什么时候释放内存,释放内存这件事儿完全由GC做了,对程序员来说是透明的.尽管如此,作为一个.Net程序员很有必要理解垃圾回收是如何工作的.这篇文章我们就来看下.Net是如何分配和管理托管内存的,之后再一步一步描述垃圾回收器工作

[JVM]成为JavaGC专家(1)—深入浅出Java垃圾回收机制

对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何工作可以帮你写出更好的Java应用. 这仅仅代表我个人的意见,但我坚信一个精通GC的人往往是一个好的Java开发者.如果你对GC的处理过程感兴趣,说明你已经具备较大规模应用的开发经验.如果你曾经想过如何正确的选择GC算法,那意味着你已经完全理解你所开发的应用的特点.当然,我们不能以偏概全,这不能作为评价一个好的开发人员的共通标准.但是,我要说的是,深入理解GC是成为一名伟

详解C#中的定时器Timer类及其垃圾回收机制_C#教程

关于C# Timer类  在C#里关于定时器类就有3个 C# Timer使用的方法1.定义在System.Windows.Forms里 C# Timer使用的方法2.定义在System.Threading.Timer类里  " C# Timer使用的方法3.定义在System.Timers.Timer类里 下面我们来具体看看这3种C# Timer用法的解释: (1)System.Windows.Forms.Timer 应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或D

[CLR via C#]21. 自动内存管理(垃圾回收机制)

原文:[CLR via C#]21. 自动内存管理(垃圾回收机制) 目录 理解垃圾回收平台的基本工作原理 垃圾回收算法 垃圾回收与调试 使用终结操作来释放本地资源 对托管资源使用终结操作 是什么导致Finalize方法被调用 终结操作揭秘 Dispose模式:强制对象清理资源 使用实现了Dispose模式的类型 C#的using语句 手动监视和控制对象的生存期 对象复活 代 线程劫持 大对象 一.理解垃圾回收平台的基本工作原理 值类型(含所有枚举类型).集合类型.String.Attribute

细述 Java垃圾回收机制→How Java Garbage Collection Works?

这是垃圾回收机制系列文章的第二篇.希望您已经读过了第一部分Java垃圾回收简介. Java垃圾回收是一个自动运行的管理程序运行时使用的内存的进程.通过GC的自动执行JVM将程序员从申请和释放内存的繁重操作中解放出来. Java垃圾回收GC初始化 作为一个自动执行的进程,程序员不需要在代码中主动初始化GC.Java提供了System.gc()和Runtime.gc()这两个hook来请求JVM调用GC进程. 尽管要求系统机制给程序员提供调用GC的机会,但是实际上这是由JVM负责决定的.JVM可以选

.Net 垃圾回收机制原理(二)

英文原文:Jeffrey Richter 编译:赵玉开 链接http://www.cnblogs.com/yukaizhao/archive/2011/11/25/dot_net_GC_2.html 上一篇文章介绍了.Net 垃圾回收的基本原理和垃圾回收执行Finalize方法的内部机制:这一篇我们看下弱引用对象,代,多线程垃圾回收,大对象处理以及和垃圾回收相关的性能计数器. 让我们从弱引用对象说起,弱引用对象可以减轻大对象带来的内存压力.弱引用(Weak References) 当程序的根对象