Android 接收大量数据如何避免频繁GC

汉书的作者2023-05-05  24

GC会stop the world。会暂停程序的执行,带来延迟的代价。所以在开发中,我们不希望GC的次数过多。

本文将讨论如何在开发中改善各种细节,从而减少GC的次数。

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

一般而言,为 Null 的对象都会被作为垃圾处理,所以将不用的对象显式地设

为 Null,有利于 GC 收集器判定垃圾,从而提高了 GC 的效率。

(2)尽量少用 Systemgc()

此函数建议 JVM进行主 GC,虽然只是建议而非一定,但很多情况下它会触发

主 GC,从而增加主 GC 的频率,也即增加了间歇性停顿的次数。

(3)尽量少用静态变量

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

(4)尽量使用 StringBuffer,而不用 String 来累加字符串

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

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

集中在短时间内大量创建新对象,特别是大对象,会导致突然需要大量内存,JVM 在面临这种情况时,只能进行主 GC,以回收内存或整合内存碎片,从而增加主 GC 的频率。

集中删除对象,道理也是一样的。 它使得突然出现了大量的垃圾对象,空闲空间必然减少,从而大大增加了下一次创建新对象时强制主 GC 的机会。

(6) 尽量少用 finalize 函数

因为它会加大 GC 的工作量, 因此尽量少用finalize 方式回收资源。

(7) 使用软引用类型

如果需要使用经常用到的, 可以使用软引用类型, 它可以尽可能将保存在内存中, 供程序调用, 而不引起 OutOfMemory。

GC就是垃圾回收器,一般来说系统会自动检测不会使用的对象或变量进行内存的释放,不需要手动调用,用Collect()就是强制进行垃圾回收,使内存得到及时的释放,让程序效率更高

给个例子:使用 Optimized 设置对第 2 代对象进行垃圾回收。

using System;

class Program

{

static void Main(string[] args)

{

GCCollect(2, GCCollectionModeOptimized);

}

}

您好,FCC认证又称为美国联邦通信认证,FCC认证是美国的一个强制性认证,主要针对的是带电的产品,FCC认证不需要验厂,申请流程相对比价简单。简单来说就是FCC认证:

是出口美国要的一个认证;

是强制性认证;

带电的产品要做;

申请认证不要验厂,相对容易。

FCC认证分2种方式:FCC SDOC和FCC ID,前者针对普通带电产品,后者针对带无线功能的产品。

FCC认证申请流程

填写申请资料;

送样测试;

测试合格后出具报告;

审核通过后颁发FCC证书。

希望可以帮到您。

GC:Java的垃圾回收器。

Java是由C++发展来的。它摈弃了C++中一些繁琐容易出错的东西。其中有一条就是这个GC。

写C/C++程序,程序员定义了一个变量,就是在内存中开辟了一段相应的空间来存值。内存再大也是有限的,所以当程序不再需要使用某个变量的时候,就需要释放这个内存空间资源,好让别的变量来用它。在C/C++中,释放无用变量内存空间的事情要由程序员自己来解决。就是说当程序员认为变量没用了,就应当写一条代码,释放它占用的内存。这样才能最大程度地避免内存泄露和资源浪费。但是这样显然是非常繁琐的。程序比较大,变量多的时候往往程序员就忘记释放内存或者在不该释放的时候释放内存了。而且释放内存这种事情,从开发角度说,不应当是程序员所应当关注的。程序员所要做的应该是实现所需要的程序功能,而不是耗费大量精力在内存的分配释放上。

Java有了GC,就不需要程序员去人工释放内存空间。当Java虚拟机发觉内存资源紧张的时候,就会自动地去清理无用变量所占用的内存空间。当然,如果需要,程序员可以在Java程序中显式地使用Systemgc()来强制进行一次立即的内存清理。

1、在什么时候GC

       首先,GC堆内存分为三部分:Young Generation,Old Generation,Permanent Generation。

        Young Generation 分为:Eden , Survivor1 , Survivor2, 新创建的对象会分配在Eden区,在经历一次Minor GC后会被移到Survivor 1区,再经历一次Minor GC后会被移到Survivor 2区,直到升至老年代,需要注意的是,一些大对象(长字符串或数组)可能会直接存放到老年代;升到老年代的对象大于剩余空间时,会发生 Full GC ,或者小于时,查看是否设置了XX:+HandlePromotionFailure(允许担保失败)参数,若允许,则只会进行Minor GC,此时可以容忍内存分配失败;若不允许,强制Full GC。

       GC与非GC时间耗时超过了GCTimeRatio的限制引发OOM,调优诸如通过NewRatio控制新生代老年代比例,通过MaxTenuringThreshold控制进入老年前生存次数等。了解GC参数,请参见 另一篇文章 。

2、对什么东西GC

       从GC root 开始搜索,搜索不到的对象和经过第一次标记、清理后仍旧没复活的对象,这类对象会被GC。

3、GC做了什么事情

        按照各部分的收集器进行空间回收,其中涉及到的收集器和GC算法参见另两篇文章:

收集器  和 GC算法 。

        新生代做复制清理、老年代做的是标记整理、标记清除

参考文献:

>

GC是垃圾回收的意思(gabage collection),内存处理器是编程人员容易出现问题的地方,忘记或者错误的内存回收导致程序或者系统的不稳定甚至崩溃,java的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,java语言没有提供释放已分配内存的俄显示操作方法。

希望能帮到你,谢谢!

1、避免使用高温处理过程。

2、在火腿炉中进行加热淬火处理。

3、控制冷却速率。

4、增加相关添加剂,如硅酸钠等。

5、使用软磨料研磨。

6、采用磨削或拉刀磨削。

7、采用表面处理技术。

8、加大模具间距。

9、调整模具及模量。

10、选择优质原料。

java中垃圾回收机制的原理

推荐一篇文章:

对高性能JAVA代码之内存管理

更甚者你写的代码,GC根本就回收不了,直接系统挂掉。GC是一段程序,不是智能,他只回收他认为的垃圾,而不是回收你认为的垃圾。

GC垃圾回收:

Grabage Collection相信学过JAVA的人都知道这个是什么意思。但是他是如何工作的呢?

首先,JVM在管理内存的时候对于变量的管理总是分新对象和老对象。新对象也就是开发者new出来的对象,但是由于生命周期短,那么他占用的内存并不是马上释放,而是被标记为老对象,这个时候该对象还是要存在一段时间。然后由JVM决定他是否是垃圾对象,并进行回收。

所以我们可以知道,垃圾内存并不是用完了马上就被释放,所以就会产生内存释放不及时的现象,从而降低了内存的使用。而当程序浩大的时候。这种现象更为明显,并且GC的工作也是需要消耗资源的。所以,也就会产生内存浪费。

JVM中的对象生命周期里谈内存回收:

对象的生命周期一般分为7个阶段:创建阶段,应用阶段,不可视阶段,不可到达阶段,可收集阶段,终结阶段,释放阶段。

创建阶段:首先大家看一下,如下两段代码:

test1:

for( int i=0; i《10000; i++)

Object obj=new Object();

test2:

Object obj=null;

for( int i=0; i《10000; i++)

obj=new Object();

这两段代码都是相同的功能,但是显然test2的性能要比test1性能要好,内存使用率要高,这是为什么呢?原因很简单,test1每次执行for循环都要创建一个Object的临时对象,但是这些临时对象由于JVM的GC不能马上销毁,所以他们还要存在很长时间,而test2则只是在内存中保存一份对象的引用,而不必创建大量新临时变量,从而降低了内存的使用。

另外不要对同一个对象初始化多次。例如:

public class A{

private Hashtable table = new Hashtable();

public A(){ table = new Hashtable();

// 这里应该去掉,因为table已经被初始化。

}

这样就new了两个Hashtable,但是却只使用了一个。另外一个则没有被引用。而被忽略掉。浪费了内存。并且由于进行了两次new操作。也影响了代码的执行速度。

应用阶段:即该对象至少有一个引用在维护他。

不可视阶段:即超出该变量的作用域。这里有一个很好的做法,因为JVM在GC的时候并不是马上进行回收,而是要判断对象是否被其他引用在维护。所以,这个时候如果我们在使用完一个对象以后对其obj=null或者objdoSomething()操作,将其标记为空,可以帮助JVM及时发现这个垃圾对象。

不可到达阶段:就是在JVM中找不到对该对象的直接或者间接的引用。

可收集阶段,终结阶段,释放阶段:此为回收器发现该对象不可到达,finalize方法已经被执行,或者对象空间已被重用的时候。

JAVA的析构方法:

可能不会有人相信,JAVA有析构函数? 是的,有。因为JAVA所有类都继承至Object类,而finalize就是Object类的一个方法,这个方法在JAVA中就是类似于C++析构函数。一般来说可以通过重载finalize方法的形式才释放类中对象。如:

public class A{

public Object a;

public A(){ a = new Object ;}

protected void finalize() throws javalangThrowable{

a = null; // 标记为空,释放对象

superfinalize(); // 递归调用超类中的finalize方法。

}

}

当然,什么时候该方法被调用是由JVM来决定的。。。。。。。。

一般来说,我们需要创建一个destory的方法来显式的调用该方法。然后在finalize也对该方法进行调用,实现双保险的做法。

由于对象的创建是递归式的,也就是先调用超级类的构造,然后依次向下递归调用构造函数,所以应该避免在类的构造函数中初始化变量,这样可以避免不必要的创建对象造成不必要的内存消耗。当然这里也就看出来接口的优势。

数组的创建:

由于数组需要给定一个长度,所以在不确定数据数量的时候经常会创建过大,或过小的数组的现象。造成不必要的内存浪费,所以可以通过软引用的方式来告诉JVM及时回收该内存。(软引用,具体查资料)。

例如:

Object obj = new char[10000000000000000];

SoftReference ref = new SoftReference(obj);

共享静态存储空间:

我们都知道静态变量在程序运行期间其内存是共享的,因此有时候为了节约内存工件,将一些变量声明为静态变量确实可以起到节约内存空间的作用。但是由于静态变量生命周期很长,不易被系统回收,所以使用静态变量要合理,不能盲目的使用。以免适得其反。

因此建议在下面情况下使用:

1,变量所包含的对象体积较大,占用内存过多。

2,变量所包含对象生命周期较长。

3,变量所包含数据稳定。

4,该类的对象实例有对该变量所包含的对象的共享需求。(也就是说是否需要作为全局变量)。

对象重用与GC:

有的时候,如数据库操作对象,一般情况下我们都需要在各个不同模块间使用,所以这样的对象需要进行重用以提高性能。也有效的避免了反复创建对象引起的性能下降。

一般来说对象池是一个不错的注意。如下:

public abstarct class ObjectPool{

private Hashtable locked,unlocked;

private long expirationTime;

abstract Object create();

abstract void expire( Object o);

abstract void validate( Object o);

synchronized Object getObject(){。};

synchronized void freeObject(Object o){。};

这样我们就完成了一个对象池,我们可以将通过对应的方法来存取删除所需对象。来维护这快内存提高内存重用。

当然也可以通过调用Systemgc()强制系统进行垃圾回收操作。当然这样的代价是需要消耗一些cpu资源。

不要提前创建对象:

尽量在需要的时候创建对象,重复的分配,构造对象可能会因为垃圾回收做额外的工作降低性能。

JVM内存参数调优:

强制内存回收对于系统自动的内存回收机制会产生负面影响,会加大系统自动回收的处理时间,所以应该尽量避免显式使用Systemgc(),

JVM的设置可以提高系统的性能。例如:

java -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xms512m -Xmx512m

具体可以查看java帮助文档。我们主要介绍程序设计方面的性能提高。

JAVA程序设计中有关内存管理的其他经验:

根据JVM内存管理的工作原理,可以通过一些技巧和方式让JVM做GC处理时更加有效。,从而提高内存使用和缩短GC的执行时间。

1,尽早释放无用对象的引用。即在不使用对象的引用后设置为空,可以加速GC的工作。(当然如果是返回值。。)

2,尽量少用finalize函数,此函数是JAVA给程序员提供的一个释放对象或资源的机会,但是却会加大GC工作量。

3,如果需要使用到,可以使用soft应用类型,它可以尽可能将读入内存而不引起OutOfMemory

4,注意集合数据类型的数据结构,往往数据结构越复杂,GC工作量更大,处理更复杂。

5,尽量避免在默认构造器(构造函数)中创建,初始化大量的对象。

6,尽量避免强制系统做垃圾回收。会增加系统做垃圾回收的最终时间降低性能。

7,尽量避免显式申请数组,如果不得不申请数组的话,要尽量准确估算数组大小。

8,如果在做远程方法调用。要尽量减少传递的对象大小。或者使用瞬间值避免不必要数据的传递。

9,尽量在合适的情况下使用对象池来提高系统性能减少内存开销,当然,对象池不能过于庞大,会适得其反

以上就是关于Android 接收大量数据如何避免频繁GC 全部的内容,包括:Android 接收大量数据如何避免频繁GC 、C# GC有什么用处、FCC-GC是什么意思等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

转载请注明原文地址:https://juke.outofmemory.cn/read/3809043.html

最新回复(0)