垃圾回收机制

垃圾回收机制
垃圾回收机制

Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾回收意味着程序不再需要的对象是“无用信息”,这些信息将被丢弃。当一个对象不再被引用时候,内存释放它占用的空间,以便空间被新对象使用。

垃圾回收能自动释放内存空间,减轻编程负担,提高编程效率,保护程序的完整性。垃圾回收是Java语言安全性策略的一个重要部分。

在C++里,释放内存需要手动处理,用delete运算符来释放分配的内存。确切地说,当应用不需要某实体时,就需要使delete语句告诉系统,可以回收这块空间了。对编码者来说,内存回收是件很麻烦、很容易出错的一件事情。相关技术论坛BBS中,在C/C++版块里总有一大堆内存泄露的话题。

Java采用的一种很方便的方法解决这个问题:垃圾回收。垃圾回收机制由JVM完全负责,编写者在抛弃对象时不必关心空间回收问题。

Ⅰ、何时对象被丢弃

Java的垃圾回收机制包含近十种算法。对这些算法中的多数,开发者不必予以关心。这里介绍其中最重要的一种:应用计数法。

提示:一个对象,可以有一个或多个引用变量指向它。当一个对象不再有任何一个引用变量指向它时,这个对象就被应用抛弃了。或者说,这个对象可以被垃圾回收机制回收了。

JVM的垃圾回收机制对堆空间做实时检测,当发现某对象的引用计数为0时,就将该对象列入待回收列表中,并不是马上予以销毁。

Ⅱ、是否丢弃即被回收

某对象被认定为没有存在的必要了,了没它所占用的内存就可以被释放。被回收的内存可以用于后续的再分配。

但是,并不是对象被抛弃后就立即被回收。JVM进程做空间回收有较大的系统开销。如果每当应用进程丢弃一个对象,就立即回收空间,势必会降低整个系统的运转效率。

前面说过,JVM的垃圾回收机制有多个算法。除了引用计数法是用来判断对象是否已被抛弃外,其他算法用来确定何时及如何做回收。JVM的垃圾回收机制要在时间和空间之间做个平衡。

因此,为了提高系统效率,垃圾回收器通常只在有对象要回收且系统需要回收时才运行。因此,用户无法知道垃圾回收发生的精确时间。

Ⅲ、干预系统回收

开发者可能对Java的垃圾回收不放心,希望在代码控制里控制JVM 的垃圾回收运作。这是不可能的事情。希望JVM及时回收垃圾,是一种需求。其实还有相反的一种需要:在某段时间内最好不要回收垃圾。要求运行速度最快的实时系统,特别是嵌入式系统,往往希望如此。

对垃圾回收机制来说,只有两个途径发消息给JVM。第一个途径就是将指向某对象的所有引用变量全部移走,相当于给JVM发了一个消息:这个对象不要了。第二个方法就是调用库方法System.gc();

调用System.gc()也仅仅是一个回收请求。JVM接收这个消息后,并不是立即做垃圾回收,而只是对几个垃圾回收算法做加权,使垃圾回收操作容易发生,或提早发生。

Java的垃圾回收机制是为所有Java应用进程服务的,而不是为某个特定的哦进程服务的。因此,任何一个进程都不能命令垃圾回收机制做什么,怎么做或做多少。

Ⅳ、finalize()方法

一个对象在运行时,可能会有一些东西与其关联。因此,当对象即将被销毁时,有时需要做一些善后工作。可以把这些操作写在finalize()方法(常称之为终止器)里,如下所示:

protected void finalize(){

//finalization code here

}

这个终止器的用途类似于C++里面的析构函数,都是自动调用的。但是,两者的调用时机不一样,使两者的表现行为有重大区别。

C++的析构函数总是当对象离开作用域时被调用。这就是说,C++析构函数的调用时机是确定的,且可以在编码中把握。Java终止器在对象被销毁时调用,被丢弃的对象何时被销毁,不得而知。而且,对于大多数场合,被丢弃对象在应用终止后仍未销毁。

在编码时候,应该考虑到这一点。例如,某对象在运行时打开了某个文件,该对象被丢弃时没有关闭这个文件,而是把文件关闭语句写在终止器里。如果文件是独占打开的,则其他对象将无法访问这个文件。如果文件是共享打开的,则另一访问该文件的对象直至程序终结仍不能读到被丢弃对象写入该文件的新内容。

当应用终止,会不会执行应用中的所有finalize()呢?根据Bruce Eckel 在《Thinking in Java》里的观点:“到程序结束的时候,并非所有收尾模块都会得到调用。”这还仅仅是指应用正常终止的场合,非正常终止呢?因此,哪些收尾操作可以放在finalize()里,是需要斟酌的。

例题:下面哪种说法是正确的,请选择(e)

(a)利用关键词delete可以明确的销毁对象

(b)对象变得不能被访问后马上被垃圾回收掉

(c)如果对象obj1可以访问对象obj2,对象obj2也可以访问对象obj1,则obj1和obj2都不适用于垃圾回收

(d)对象一旦变得适用于垃圾回收,则在被销毁之前保持这种适用性

(e)对于对象obj1可以访问适用于垃圾回收的对象obj2,则obj1同样适用于垃圾回收

解析:如果所有声明的对象引用都是来自其他适合进行垃圾回收的对象,这个对象时最适合进行垃圾回收的。所以,如果对象obj2适合进行垃圾回收,而且对象obj1包含执行obj2的引用,那么对象obj1也必须进行垃圾回收。Java 没有delete关键词。对象在变得不能被访问之后不必马上作为垃圾被收集,该对象只是适合垃圾回收。

只要对象可以被任何存活的线程访问,就不适合进行垃圾回收,一个已经成为垃圾回收目标的对象还可以消除这种适合性,当对象的finalize()方法创建了一个指向该对象的合法引用时,就可以出现这种情况。

下面的代码中,什么时候myObject对象适合垃圾回收?(c)

public class Gc {

public static void main(String[] args) {

new Gc().UseObject();

}

private void UseObject(){

String anObject=AllocateObject();

System.out.println(anObject);

}

private String AllocateObject(){

String myObject=new String("when will I deleted");

return myObject;

}

}

(a)当AllocateObject()方法执行完毕

(b)当System.out.println(anObject)方法执行完毕

(c)当UseObject()方法执行完毕

(d)当main()方法执行完毕

解析:当指向某个对象的最后一个引用被删除,那么该对象就可以被删除。上述代码中,最后一个引用是anObject引用,即在UseObject()方法执行完毕后删除。

例子2:对于最初由arg1所引用的对象,标出在如下程序中的什么地方该对象

变得适用于垃圾回收?

public class Gc2 {

public static void main(String[] args) {

String msg;

String pre="This program was called with";

String post="at first argument";

String arg1=new

String((args.length>0)?""+args[0]+"":"");

msg=arg1;

arg1=null;//(1)

msg=pre+msg+post;//(2)

pre=null;//(3)

System.out.println(msg);

msg=null;//(4)

post=null;//(5)

args=null;//(6)

}

}

请选择正确的答案(b)

(a)从标签为(1)的那一行以后

(b)从标签为(2)的那一行以后

(c)从标签为(3)的那一行以后

(d)从标签为(4)的那一行以后

(e)从标签为(5)的那一行以后

(f)从标签为(6)的那一行以后

解析:在标签(1)之前,最初被arg1引用的String对象由msg和arg1来表示。在标签(1)之后,该String对象就只由msg来表示。在标签(2)之后,引用msg被赋予一个null值,即不再指向该对象的引用,而在标签(2)之后,该对象已经没有引用了。

请指出下面代码中标记的对象,从哪里开始可以被回收(e);

public class Gc3 {

public static void main(String[] args) {

Vector v1=new Vector();//标记对象

Vector v2=new Vector();//(1)

v1.add("This");//(2)

v1.add(v2);//(3)

String s=(String)v1.elementAt(0);//(4)

v1=v2;//(5)

v2=v1;//(6)

v1.add(s);

}

}

请选择正确的答案(e)

(a)(1处)

(b)(2处)

(c)(3处)

(d)(4处)

(e)(5处)

(f)(6处)

解析:从程序代码中可以看到,该对象创建后赋给v1引用,一直到(5)处,v1的引用都没有变化,而在(5)处v1引用了另外一个对象v2,以后代码中都没有引用该对象。

垃圾回收机制

浅谈JAVA垃圾回收机制 摘要:垃圾回收机制是JAVA的主要特性之一,在对垃圾回收机制进行概述之后,本文从“失去引用”和“离开作用域”这两个角度分析了JAVA程序中的对象在何种条件下满足垃圾回收的要求。最后,本文简要介绍了垃圾回收机制的两个特性。 关键词:JAVA;垃圾回收机制;离开作用域;失去引用;自动性;不可预期性 作为一种适应于Internet计算环境、面向对象并具有平台无关性的编程语言,JAVA早已确立了在IT界的地位,并因网络日益广泛的应用而变得越来越重要。因此,在高校中JAVA也逐渐受到更多教师和学生的重视。 实际上,JAVA源自C++语言。但JAVA语言避免了C++中晦涩的结构,成功翻越了多重继承机制的恼人问题;JAVA的垃圾回收机制显著地提高了生产率,降低了复杂度;在网络背景下使用虚拟机,以及有关安全性和动态加载的一系列设计选择,迎合了正在出现的需求和愿望。这些特性使Java不仅成为现有程序员的武器,而且也为新的程序员创造了繁荣的市场空间。在JAVA语言的上述特性中,本文主要分析其垃圾回收机制。 一、JAVA垃圾回收机制概述 在VB、C++等某些程序设计语言中,无论是对象还是动态配置的资源或内存,都必须由程序员自行声明产生和回收,否则其中的资源将不断消耗,造成资源的浪费甚至死机。由于要预先确定占用的内存空间是否应该被回收是非常困难的,这就导致手工回收内存往往是一项复杂而艰巨的工作。因此,当使用这些程序设计语言编程时,程序员不仅要考虑如何实现算法以满足应用,还要花费许多精力考虑合理使用内存避免系统崩溃。 针对这种情况,JAVA语言建立了垃圾回收机制。JAVA是纯粹的面向对象的编程语言,其程序以类为单位,程序运行期间会在内存中创建很多类的对象。这些对象在完成任务之后,JAVA 的垃圾回收机制会自动释放这些对象所占用的空间,使回收的内存能被再次利用,提高程序的运行效率。垃圾回收不仅可以提高系统的可靠性、使内存管理与类接口设计分离,还可以使开发者减少了跟踪内存管理错误的时间,从而把程序员从手工回收内存空间的繁重工作中解脱出来。 JAVA垃圾回收机制另一个特点是,进行垃圾回收的线程是一种低优先级的线程,在一个Java 程序的生命周期中,它只有在内存空闲的时候才有机会运行。 下面本文从“对象的失去引用”和“对象离开作用域”这两个方面进行分析,探讨JAVA程序中的对象什么时候可以被当作垃圾来进行回收。 二、对象的失去引用 通过下面的一段JAVA程序(例1),我们可以讨论程序中的对象是否已经符合垃圾回收的条

JVM的垃圾回收机制小读

JVM的垃圾回收机制小读 技术2010-05-09 19:41:04 阅读20 评论2 字号:大中小订阅 今天下午突然遇到了一个内存漏洞的问题,所以上网查了查,结果看到了一篇文章,说的是jvm的垃圾回收机制,下面粘过来,看了好久才看完的,说的思路有点含糊,还给带了点代码,这样还不错……对JVM 的内存管理机制有加深了一层理解哈………… 下面是那篇文章,喜欢的可以看看…………O(∩_∩)O………… Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立, 但是它们不需要程序代码来显式地释放。 引言 Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。一般来说,堆的是由垃圾回收来负责的,尽管JVM规范并不要求特殊的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,JVM在实现的时候都有一个由垃圾回收所管理的堆。垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。 垃圾收集的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾收集意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。事实上,除了释放没用的对象,垃圾收集也可以清除内存记录碎片。由于创建对象和垃圾收集器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆 的一端,JVM将整理出的内存分配给新的对象。 垃圾收集能自动释放内存空间,减轻编程的负担。这使Java 虚拟机具有一些优点。首先,它能使编程效率提高。在没有垃圾收集机制的时候,可能要花许多时间来解决一个难懂的存储器问题。在用Java 语言编程的时候,靠垃圾收集机制可大大缩短时间。其次是它保护程序的完整性,垃圾收集是Java语言 安全性策略的一个重要部份。 垃圾收集的一个潜在的缺点是它的开销影响程序性能。Java虚拟机必须追踪运行程序中有用的对象,而且最终释放没用的对象。这一个过程需要花费处理器的时间。其次垃圾收集算法的不完备性,早先采用的某些垃圾收集算法就不能保证100%收集到所有的废弃内存。当然随着垃圾收集算法的不断改进以及软硬件运行效率的不断提升,这些问题都可以迎刃而解。 垃圾收集的算法分析

java垃圾回收机制

上次讲到引用类型和基本类型由于内存分配上的差异导致的性能问题。那么今天就来聊一下和内存释放(主要是gc)有关的话题。 事先声明一下:虽说sun公司已经被oracle吞并了,但是出于习惯,同时也为了偷懒节省打字,以下仍然称之为sun公司。 ★jvm的内存 在java虚拟机规范中(具体章节请看“这里”),提及了如下几种类型的内存空间: ◇栈内存(stack):每个线程私有的。 ◇堆内存(heap):所有线程公用的。 ◇方法区(method area):有点像以前常说的“进程代码段”,这里面存放了每个加载类的反射信息、类函数的代码、编译时常量等信息。 ◇原生方法栈(native method stack):主要用于jni中的原生代码,平时很少涉及。 关于栈内存(stack)和堆内存(heap),已经在上次的帖子中扫盲过了,大伙儿应该有点印象。由于今天咱们要讨论的“垃圾回收”话题,主要是和堆内存(heap)有关。其它的几个玩意儿不是今天讨论的重点。等以后有空了,或许可以单独聊一下。 ★垃圾回收机制简介 其实java虚拟机规范中并未规定垃圾回收的相关细节。垃圾回收具体该怎么搞,完全取决于各个jvm的设计者。所以,不同的jvm之间,gc的行为可能会有一定的差异。下面咱拿sun官方的jvm来简单介绍一下gc的机制。 ◇啥时候进行垃圾回收? 一般情况下,当jvm发现堆内存比较紧张、不太够用时,它就会着手进行垃圾回收工作。但是大伙儿要认清这样一个残酷的事实:jvm进行gc的时间点是无法准确预知的。因为gc启动的时刻会受到各种运行环境因素的影响,随机性太大。 虽说咱们无法准确预知,但如果你想知道每次垃圾回收执行的情况,还是蛮方便的。可以通过jvm的命令行参数“-xx:+printgc”把相关信息打印出来。 另外,调用system.gc()只是建议jvm进行gc。至于jvm到底会不会做,那就不好说啦。通常不建议自己手动调用system.gc(),还是让jvm自行决定比较好。另外,使用jvm命令行参数“-xx:+disableexplicitgc”可以让system.gc()不起作用。 ◇谁来负责垃圾回收? 一般情况下,jvm会有一个或多个专门的垃圾回收线程,由它们负责清理回收垃圾内存。 ◇如何发现垃圾对象? 垃圾回收线程会从“根集(root set)”开始进行对象引用的遍历。所谓的“根集”,就是正在运行的线程中,可以访问的引用变量的集合(比如所有线程当前函数的参数和局部变量、当前类的成员变量等等)。垃圾回收线程先找出被根集直接引用的所有对象(不妨叫集合1),然后再找出被集合1直接引用的所有对象(不妨叫集合2),然后再找出被集合2直接引用的所有对象......如此循环往复,直到把能遍历到的对象都遍历完。 凡是从根集通过上述遍历可以到达的对象,都称为可达对象或有效对象;反之,则是不可达对象或失效对象(也就是垃圾)。 ◇如何清理/回收垃圾? 通过上述阶段,就把垃圾对象都找出来。然后垃圾回收线程会进行相应的清理和回收工作,包括:把垃圾内存重新变为可用内存、进行内存的整理以消除内存碎片、等等。这个过程会涉及到若干算法,有兴趣的同学可以参见“这里”。限于篇幅,咱就不深入聊了。 ◇分代 早期的jvm是不采用分代技术的,所有被gc管理的对象都存放在同一个堆里面。这么做的缺点比较明显:每次进行gc都要遍历所有对象,开销很大。其实大部分的对象生命周期都很短(短命对象),只有少数对象比较长寿;在这些短命对象中,又只有少数对象占用的内存空间大;其它大量的短命对象都属于小对象(很符合二八原理)。 有鉴于此,从jdk 1.2之后,jvm开始使用分代的垃圾回收(generational garbage collection)。jvm把gc相关的内存分为年老代(tenured)和年轻代(nursery)、持久代(permanent,对应于jvm规范的方法区)。大部分对象在刚创建时,都位于年轻代。如果某对象经历了几轮gc还活着(大龄对象),就把它移到年老代。另外,如果某个对象在创建时比较大,可能就直接被丢到年老代。经过这种策略,使得年轻代总是保存那些短命的小对象。在空间尺寸上,年轻代相对较小,而年老代相对较大。 因为有了分代技术,jvm的gc也相应分为两种:主要收集(major collection)和次要收集(minor collection)。主要收集同时清理年老代和年轻代,因此开销很大,不常进行;次要收集仅仅清理年轻代,开销很小,经常进行。 ★gc对性能会有啥影响? 刚才介绍了gc的大致原理,那gc对性能会造成哪些影响捏?主要有如下几个方面: ◇造成当前运行线程的停顿 早期的gc比较弱智。在它工作期间,所有其它的线程都被暂停(以免影响垃圾回收工作)。等到gc干完活,其它线程再继续运行。所以,早期jdk的gc一旦开始工作,整个程序就会陷入假死状态,失去各种响应。

JAVA垃圾回收机制论文

JAVA的垃圾回收机制探究 摘要:垃圾回收机制是java的主要特性之一,在对垃圾回收机制的意义进行概述之后,文章分析了java程序中的对象在何种条件下满足垃圾回收的要求以及在垃圾回收中应该注意的几个问题。 关键词:java;垃圾回收机制 中图分类号:tp312文献标识码:a文章编号:1007-9599 (2011) 24-0000-01 java garbage collection mechanism study wang xin (daqing petroleum administration communications company,daqing163453,china) abstract:java garbage collection mechanism is one of the main features of the garbage collection mechanism for an overview of the meaning,the paper analyzes the objects in the java program to meet the conditions under which the requirements of garbage collection and garbage collection should be noted a few questions. keywords:java;garbage collection mechanism 一、垃圾收集的意义 在c++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。jvm的

详细介绍Java垃圾回收机制

详细介绍Java垃圾回收机制 垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变。垃圾收集的目的在于清除不再使用的对象。GC通过确定对象是否被活动对象引用来确定是否收集该对象。GC首先要判断该对象是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。 引用计数收集器 引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象(不是引用都一个引用计数。当一个对象被创建时,且将该对象分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b 引用的对象+1),但当一个对象的某个引用超过了生命周期或者被设置为一个新值时,对象的引用计数减1。任何引用计数为0的对象可以被当作垃圾收集。当一个对象被垃圾收集时,它引用的任何对象计数减1。 优点:引用计数收集器可以很快的执行,交织在程序运行中。对程序不被长时间打断的实时环境比较利。 缺点:无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0. 跟踪收集器 早期的JVM使用引用计数,现在大多数JVM采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,GC必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。 下一步,GC要删除不可到达的对象。删除时,有些GC只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。因此,许多GC可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。

Java垃圾回收机制

一.谁在做Garbage Collection? 一种流行的说法:在C++里,是系统在做垃圾回收;而在Java里,是Java自身在做。 在C++里,释放内存是手动处理的,要用delete运算符来释放分配的内存。这是流行的说法。确切地说,是应用认为不需要某实体时,就需用delete 告诉系统,可以回收这块空间了。这个要求,对编码者来说,是件很麻烦、很难做到的事。随便上哪个BBS,在C/C++版块里总是有一大堆关于内存泄漏的话题。 Java采用一种不同的,很方便的方法:Garbage Collection。垃圾回收机制放在JVM里。JVM完全负责垃圾回收事宜,应用只在需要时申请空间,而在抛弃对象时不必关心空间回收问题。 二.对象在啥时被丢弃? 在C++里,当对象离开其作用域时,该对象即被应用抛弃。 在Java里,对象的生命期不再与其作用域有关,而仅仅与引用有关。 Java的垃圾回收机制一般包含近十种算法。对这些算法中的多数,我们不必予以关心。只有其中最简单的一个:引用计数法,与编码有关。 一个对象,可以有一个或多个引用变量指向它。当一个对象不再有任何一个引用变量指向它时,这个对象就被应用抛弃了。或者说,这个对象可以被垃圾回收机制回收了。这就是说,当不存在对某对象的任何引用时,就意味着,应用告诉JVM:我不要这个对象,你可以回收了。 JVM的垃圾回收机制对堆空间做实时检测。当发现某对象的引用计数为0时,就将该对象列入待回收列表中。但是,并不是马上予以销毁。 三.丢弃就被回收? 该对象被认定为没有存在的必要了,那么它所占用的内存就可以被释放。被回收的内存可以用于后续的再分配。 但是,并不是对象被抛弃后当即被回收的。JVM进程做空间回收有较大的系统开销。如果每当某应用进程丢弃一个对象,就立即回收它的空间,势必会使整个系统的运转效率非常低下。前面说过,JVM的垃圾回收机制有多个算法。除了引用计数法是用来判断对象是否已被抛弃外,其它算法是用来确定何时及如何做回收。 JVM的垃圾回收机制要在时间和空间之间做个平衡。 因此,为了提高系统效率,垃圾回收器通常只在满足两个条件时才运行:即有对象要回收且系统需要回收。切记垃圾回收要占用时间,因此,Java

java垃圾回收机制是怎样的

java垃圾回收机制是怎样的 手动管理内存 在介绍现代版的垃圾回收之前,我们先来简单地回顾下需要手 动地显式分配及释放内存的那些日子。如果你忘了去释放内存,那么这块内存就无法重用了。这块内存被占有了却没被使用。这种场景被称之为内存泄露。 下面是用C写的一个手动管理内存的简单例子: intsend_request() { size_tn=read_size(); int*elements=malloc(n*sizeof(int)); if(read_elements(n,elements)

11intsend_request(){size_tn=read_size();stared_ptrelements= make_shared();if(read_elements(n,elements)

垃圾收集与处理管理制度

垃圾收集与处理管理制度 一、目的: 确保分包方提供的服务达到我司制定的工作标准,为业主、住户营造清洁、卫生、舒适优雅的居住环境。 二、范围: 适用于XX管理处清洁分包单位 三、职责: 1.负责对管理小区内环境卫生、清洁进行检查、监督、指导。 2.按有关规定和要求及时处理垃圾处理过程中发生的不合格现象,发现重大问题及时上报主管领导。 一、工作要求: 1.垃圾的分类处理: 1.1工程垃圾:瓦砾、碎砖、灰渣等坚硬的工程垃圾应用斗车或其它装运工具运送到小区指定地点倒放,禁止倒在垃圾中转站内。路面灰尘、泥沙等粉尘性垃圾在运送途中应加以遮挡,防止垃圾掉落或飞扬引起二次污染。 1.2生活垃圾:清洁工清洁时的少量垃圾可倒入附近的垃圾桶内,量大的垃圾应直接运送到小区内的垃圾中转站内。清洁工应在规定时间收集垃圾桶内的垃圾并转运至垃圾中转站。 2.垃圾中转站的垃圾应日产日清,如垃圾较多影响垃圾存放时,可增加清运次数。 3.保洁班人员应负责垃圾中转站周围的卫生,保证垃圾中转站里的垃圾存放齐整,地面无散落的垃圾。 3.1负责每天一次冲洗垃圾中转站地面。 3.2每天应对垃圾中转站进行一次消杀工作。 4垃圾中转站的卫生标准: 4.1地面无散落垃圾、无污水、污渍;墙面无粘附物,无明显污迹; 4.2垃圾做到日产日清; 4.3所有垃圾集中堆放在堆放点,做到合理、卫生、四周无散积垃圾;

4.4可作废品回收的垃圾应另行存放; 4.5垃圾站应保持清洁无异味,每天应定时喷洒药水,防止蚊蝇滋长; 4.6按要求做好垃圾袋装化。 5.垃圾车撒落在大院内的垃圾由垃圾清运人员负责扫净。 6.综合部应按相关标准检查保洁工的工作情况,并记录。

C# 内存(垃圾)自动回收机制

基本概念: CLR-所有为.NET编写的程序(包括用C#编写的COM+组件)都运行在称为通用语言运行库(Common Language Runtime,CLR)的环境内。为运行于CLR内编写的应用程序被看作是托管代码。托管代码可利用CLR提供的服务。某些这类服务,如垃圾收集(Garbage Collection), 是自动提供的。其他服务,如对软件的版本编号,则要求程序员干预。 为什么会有垃圾回收机制: 如果我们的内存足够大,大到有无数的连续内存块给我们的应用程序调用,那么垃圾回收机制就很鸡肋了,但实际上是,我们的内存永远无法满足我们应用程序的饥渴的需求,内存越大,应用程序所需求的内存也越大。有那么一部分程序申请了内存(以堆的形式),但是并不是一直在用,用句粗话就是“占着**不**”的意思,为了干掉这么一些个浪费社会资源的存在,内存回收机制的诞生就迫在眉睫了。 程序如何申请内存: CLR启动应用程序时创建和初始化托管堆。另外,CLR初始化指向堆的基地址的堆指针。堆指针包含下一个可用内存块的地址。图1—1展示了初始化后且在创建任何对象之前的托管堆。 当在C#中用关键词new 创建对象时,CLR 从堆分配内存并将堆指针增加使之指向下一个可 用的内存块。图1-2 显示了应用程序中首次调用new 后的堆。

CLR 从托管堆分配内存可以比从传统非托管的Win32 堆分配内存快得多。在典型非托管的Win32 堆中,内存的分配不是顺序的。当从Win32 堆分配内存时,堆必须检查以寻找满足请示的内存块。一旦找到内存块,堆维护的数据结构就必须更新。另一方面,托管堆则只需增加堆指针。 开始垃圾回收: 在某些时候,堆指针增加到了堆的顶部,不再有内存可供分配。出现这种情况时,一种被称为垃圾收集(Garbage Collection)的过程开始释放不再使用的资源。垃圾收集(Garbage Collection)以构建应用程序正在使用的所有对象的列表为开始。垃圾收集器查找的开始之处事应用程序的根,其中包括: * 全局对象引用 * 静态对象引用 * 局部变星(对当前正在执行的方法而言) * 参数(对当前正在执行的方法而言) * 包含对象引用的CPU寄存器 应用程序根的整个列表由允许垃圾收集器向运行库查询的JIT编译器加以维护。一旦识别出根的整个列表,垃圾收集器就访问每个根的每一个对象引用。如果根包含对其他对象的引用,也会将这些引用加入到列表中。一旦垃圾收集器已经访问整个对象引用链,就检查堆栈以查找末在列表中的任何引用。不在列表中的引用被视为不能访问并可以释放。释放不能访问对象所占的内存后,垃圾收集器就压缩堆并将堆指针设为堆的下一个可用块。 到这里可能会引起怀疑:前面辛辛苦苦创建的内存自动分配的速度和性能优势,通过这样的垃圾搜集机制不是都浪费了吗?嘿嘿,这还不是事情的全部。垃圾收集器使用一种称为通用垃圾收集(Generational Garbage Collection)的技术优化垃圾收集过程。通用垃圾收集假定关于应用应用程序的以下情况为真: * 新对象有比旧对象短的寿命

Java垃圾回收机制

Java垃圾回收机制 1、引用计数:没有应用到JVM,只是理论说明。 2、活的对象:可以追溯到堆栈和静态存储区 3、Stop and copy:停止工作,将活的对象从一个堆复制到另一个堆,紧密排列,然后剩下 的就是垃圾对象了。问题:(1)空间;(2)复制:垃圾少,要复制大量活的对象 4、Mark and sweep:标记每个对象是否活对象,标记完所有对象,清楚非活的对象。问题: 空间不连续。 5、如果垃圾很少,复制效率降低的话就用,标记清扫;如果不连续空间太多的话,则转到 停止复制 6、优化方法:Just-In-Time 和HotSoft,前者翻译成本地机器码,后者惰性编译,只在必 要时编译代码,不被执行的代码不被编译,代码每次执行的时候都会做一定的优化。7、避免内存泄漏或者不当使用的方法:(1)重复使用已经初始化的对象,尽量少声明对象; (2)try catch finally语句中清楚不需要的对象;(3)执行完毕清楚不必要的对象,当然是那些引用可能被保存的对象。 尽管java虚拟机和垃圾回收机制管理着大部分的内存事务,但是在java软件中还是可能存在内存泄漏的情况。的确,在大型工程中,内存泄漏是一个普遍问题。避免内存泄漏的第一步,就是要了解他们发生的原因。这篇文章就是要介绍一些常见的缺陷,然后提供一些非常好的实践例子来指导你写出没有内存泄漏的代码。一旦你的程序存在内存泄漏,要查明代码中引起泄漏的原因是很困难的。同时这篇文章也要介绍一个新的工具来查找内存泄漏,然后指明发生的根本原因。这个工具容易上手,可以让你找到产品级系统中的内存泄漏。 垃圾回收(GC)的角色 虽然垃圾回收关心着大部分的问题,包括内存管理,使得程序员的任务显得更加轻松,但是程序员还是可能犯些错误导致内存泄漏问题。GC(垃圾回收)通过递归对所有从“根”对象(堆栈中的对象,静态数据成员,JNI句柄等等)继承下来的引用进行工作,然后标记所有可以访问的活动着的对象。而这些对象变成了程序唯一能够操纵的对象,其他的对象都被释放了。因为GC使得程序不能够访问那些被释放的对象,所以这样做是安全的。 内存管理可以说是自动的,但是这并没有让程序员脱离内存管理问题。比方说,对于内存的分配(还有释放)总是存在一定的开销,尽管这些开销对程序员来说是隐含的。一个程序如果创建了很多对象,那么它就要比完成相同任务而创建了较少对象的程序执行的速度慢(如果其他的条件都相同)。

java垃圾回收机制总结

垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身 一个对象在运行时,可能会有一些东西与其关连,因此,当对象即将销毁时,有时需要做一些善后工作,可以把这些操作写在finalize()方法(常称之为终止器)。 protected void finalize(){ // code here } 这个终止器的用途类似于C++里的析构函数,而且都是自动调用的,但是,两者的调用时机不一样,使两者的表现行为有重大区别。C++的析构函数总是当对象离开作用域时被调用。这就是说,C++析构函数的调用时机是确定的,且是被应用判知的,但是,JAVA终止器却是在对象被销毁时调用,一旦垃圾收集器准备好释放无用对象占用的存储空间,它首先调用那些对象的finalize()方法,然后才真正回收对象的内在。 我们知道,许多程序设计语言都允许在程序运行期动态地分配内存空间。分配内存的方式多种多样,取决于该种语言的语法结构。但不论是哪一种语言的内存分配方式,最后都要返回所分配的内存块的起始地址,即返回一个指针到内存块的首地址。 当已经分配的内存空间不再需要时,换句话说当指向该内存块的句柄超出了使用范围的时候,该程序或其运行环境就应该回收该内存空间,以节省宝贵的内存资源。 在C,C++或其他程序设计语言中,无论是对象还是动态配置的资源或内存,都必须由程序员自行声明产生和回收,否则其中的资源将消耗,造成资源的浪费甚至死机。但手工回收内存往往是一项复杂而艰巨的工作。因为要预先确定占用的内存空间是否应该被回收是非常困难的!如果一段程序不能回收内存空间,而且在程序运行时系统中又没有了可以分配的内存空间时,这段程序就只能崩溃。通常,我们把分配出去后,却无法回收的内存空间称为"内存渗漏体(Memory Leaks)"。 以上这种程序设计的潜在危险性在Java这样以严谨、安全著称的语言中是不允许的。但是Java语言既不能限制程序员编写程序的自由性,又不能把声明对象的部分去除(否则就不是面向对象的程序语言了),那么最好的解决办法就是从Java程序语言本身的特性入手。于是,Java技术提供了一个系统级的线程(Thread),即垃圾收集器线程(Garbage Collection Thread),来跟踪每一块分配出去的内存空间,当Java 虚拟机(Java Virtual Machine)处于空闲循环时,垃圾收集器线程会自动检查每一快分配出去的内存空间,然后自动回收每一快可以回收的无用的内存块。 垃圾收集器线程是一种低优先级的线程,在一个Java程序的生命周期中,它只有在内存空闲的时候才有机会运行。它有效地防止了内存渗漏体的出现,并极大可能地节省了宝贵的内存资源。但是,通过Java虚拟机来执行垃圾收集器的方案可以是多种多样的。 下面介绍垃圾收集器的特点和它的执行机制: 垃圾收集器系统有自己的一套方案来判断哪个内存块是应该被回收的,哪个是不符合要求暂不回收的。垃圾收集器在一个Java程序中的执行是自动的,不能强制执行,即使程序员能

java垃圾回收机制原理

记得部门老大曾经说过,java的垃圾回收机制对于java体系结构的学习非常重要。这里将阅读的一些文献整理总结出来,记述java的几种垃圾回收算法。 垃圾回收算法有两个基本的问题:1.必须检测到垃圾对象。2.必须重新声明被垃圾对象占用的堆空间并且让堆空间可用。 可达性(reachability) 一个对象是可达的,当且仅当从可执行程序的根集开始有引用路径能访问该对象。 根集(roots set) 包括:1.局部变量的对象引用,栈元素以及任何类变量的对象引用 2.任何对象引用,如string 3.任何传递给本地方法的对象引用 4.JVM的运行时数据区的任何部分 引用记数(reference counting) 这是一种不使用根集的垃圾回收算法。基本思想是:当对象创建并赋值时该对象的引用计数器置1,每当对象给任意变量赋值时,引用记数+1;一旦退出作用域则引用记数-1。一旦引用记数变为0,则该对象可以被垃圾回收。 引用记数有其相应的优势:对程序的执行来说,每次操作只需要花费很小块的时间。这对于不能被过长中断的实时系统来说有着天然的优势。 但也有其不足:不能够检测到环(两个对象的互相引用);同时在每次增加或者减少引用记数的时候比较费时间。 在现代的垃圾回收算法中,引用记数已经不再使用。 追踪算法(tracing) 基于根集的最基本算法。基本思想是:每次从根集出发寻找所有的引用(称为活对象),每找到一个,则对其做出标记,当追踪完成之后,所有的未标记对象便是需要回收的垃圾。 追踪算法基于标记并清除.这个垃圾回收步骤分为两个阶段:在标记阶段,垃圾回收器遍历整棵引用树并标记每一个遇到的对象。在清除阶段,未标记的对象被释放,并使其在内存中可用。 紧凑算法(compacting) 在追踪算法中,每次被释放的对象会让堆空间出现碎片,这会使得内存的页面管理变得非常不稳定,可能在还有足够内存空间时就发生溢出,这对于本来就紧张的JVM内存资源来说是非常不利的。由此出现了紧凑算法。

java垃圾回收机制介绍

Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。一般来说,堆的是由垃圾回收来负责的,尽管JVM规范并不要求特殊的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,JVM在实现的时候都有一个由垃圾回收所管理的堆。垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。 垃圾收集的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾收集意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。事实上,除了释放没用的对象,垃圾收集也可以清除内存记录碎片。由于创建对象和垃圾收集器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内存分配给新的对象。 垃圾收集能自动释放内存空间,减轻编程的负担。这使Java 虚拟机具有一些优点。首先,它能使编程效率提高。在没有垃圾收集机制的时候,可能要花许多时间来解决一个难懂的存储器问题。在用Java语言编程的时候,靠垃圾收集机制可大大缩短时间。其次是它保护程序的完整性,垃圾收集是Java语言安全性策略的一个重要部份。 垃圾收集的一个潜在的缺点是它的开销影响程序性能。Java虚拟机必须追踪运行程序中有用的对象,而且最终释放没用的对象。这一个过程需要花费处理器的时间。其次垃圾收集算法的不完备性,早先采用的某些垃圾收集算法就不能保证100%收集到所有的废弃内存。当然随着垃圾收集算法的不断改进以及软硬件运行效率的不断提升,这些问题都可以迎刃而解。 垃圾收集的算法分析 Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾收集算法一般要做2件基本的事情:(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。 大多数垃圾回收算法使用了根集(root set)这个概念;所谓根集就量正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。垃圾收集首选需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。而根集通过任意路径不可达的对象符

UE3引擎的垃圾回收机制略说

要进行垃圾回收,有两个条件:一、要知道所有的对象放在哪里,即内存中的位置。二、要知道对象的这块内存上,数据表示的是什么意思,是一个Float 数还是Int数还是一个对象指针的值。具备这两个条件,才可以遍历所有的对象,找出没有被引用的对象,然后删除释放掉。U3是如何满足这两个条件的呢,先看第一个。 U3里几乎所有的类,都以UObject为基类,一般核心基类都尽量做得简洁明了,但UObject却很复杂,有大量的static成员变量和成员函数,来实现包括对象构造、对象管理、垃圾回收、资源加载等功能。 首先看GObjObjects这个static TArray指针数组,记录着游戏启动后构造的一个一个对象的地址。对象的构造都是通过StaticConstructObject()函数进行,它首先根据名字查找,该对象是否已经存在,若不存在,则调用malloc()申请内存,然后设置DefaultProperties值啊Config值啊等等,然后调用AddObject()将对象放入GObjObjects数组中,同时也放入GObjHash的哈希表中,方便以后查找对象。当然,不会直接放入GObjObjects数组的最后,而是有一个TArray GObjAvailable数组,记录着GObjObjects数组中为NULL的项的Index,这些是被垃圾回收的对象留下来的坑。所以一个对象放入数组中后,其Index值就永远不会变,直到本身逝去,死后留坑。 所以要遍历所有的对象,只需要遍历GObjObjects数组即可。那如何判断对象内存中的数据,是表示Float还是int还是对象指针呢?UE3是用C++写的,C++本身不支持元数据啊,那怎么办呢,关键就在脚本。脚本一般用来编写游戏逻辑,方便之用,UE3却是以脚本为根基。几乎所有的类,都需要先定义在脚本里,然后编译自动生成.h头文件,然后手工添加.cpp文件来实现native的函数。编译脚本的时候,会记录类中所有变量和函数的元数据,保存在生成的.u文件中,运行加载.u的时候,每个类每个变量每个函数都会有相应的UObject对象与之对应,就相当于元数据了。比如Actor类中的DrawScale变量,是一个Float类型,以一个UFloatProperty对象来表示,UFloatProperty继承自UProperty,UProperty 继承自UField,UField继承自UObject。为了记录一个变量的信息,继承了这么多层次,而且UObject又是那么庞大,真是大方。所以游戏运行起来的时候,先构造一大堆的UFloatProperty,UIntProperty,UStructProperty对象放入GObjObjects数组中,当脚本数也就是类的数量很多时,这一大堆就很壮观了,繁荣程度稍后再讲。 好了,现在可以遍历所有的对象,又能根据从脚本中来的元数据来判断数据类型,就可以进行垃圾回收了。 垃圾回收分为二步,一是遍历所有对象,给需要回收的对象打上标识。具体过程是,遍历GObjObjects数组,找出有RF_RootSet这些标识的对象,放入一个数组中,然后将其它所有的对象标识为RF_Unreachable。然后遍历刚才的数组,分析对象中成员变量的类型,比如是GCRT_Object类型,则知道它是一个对象指针,然后将它指向的对象清除掉Unreachable标识。这样做完后,还有RF_Unreachable标识的对象,就是没有再被引用的对象。第二步水到渠成,回收对象,释放内存。 这就是内存回收的大概印象了,若论起细节来,其实也还没看懂。 刚才未说完的UFloatProperty这些对象,到底有多少呢?写了个小函数,遍历GObjObjects数组,将所有对象的FullName和Index打印出来,一看不得不,对象总共近9万个,而UFloatProperty这类对象,居然约有6万个,足足占三分

关于建立有害垃圾回收处理机制的建议

案类案号:提案第20140017号 案由:关于建立有害垃圾回收处理机制的建议 提出人:民进广东省委会(共1名) 办理类型:未分派 承办单位: 内容: 案由: 近几年,环境保护问题成为各种媒体和民众的热门话题,如何处理好生活中产生的垃圾,特别是有害垃圾的回收处理,是保护环境、开展生态文明建设的重要一环,也是关系到人民群众生活质量的一项重要工作。当前,广州已实施生活垃圾分类处理,省内其他地方还没有明确的开展。从广州目前的情况来看,由于设施、民众意识等各方面因素,令垃圾分类之路举步维艰,其中的有毒有害垃圾回收处理状况更不尽如人意。因此,从全省实际出发,自上而下建立一套完善的有害生活垃圾处理机制就显得十分紧迫。 一、目前,主要存在以下几个问题 (一)重视程度不足。近年来,从国家到各省直到市县、镇村,大范围地开展了生活垃圾分类试点工作,部分城市也积累了一定的经验,但对生活垃圾中有害垃圾的分类与处理,却存在着重视程度不够,没有明确的建章立法。 (二)宣传力度不足。由于政府的宣传与指引不足,大家对什么是生活中的有害垃圾也不大清楚,导致了市民在响应政府号召进行家庭生活垃圾分类过程中,并没有重视有害垃圾与其它可回收生活垃圾的区分,也没有细致地把有害垃圾筛选出来。 (三)分类开展不足。在城管环卫部门进行生活垃圾收集时,并没有对有害垃圾进行二次分类收集,也没有进行分类运送,反而只在垃圾中转站进行汇总,与其它已分类生活垃圾混装处理,令市民所做的垃圾分类也白做了。 (四)财政扶持不足。各地政府由于财政等原因,对生活垃圾中有害垃圾的最终处置方式仍然停留在销毁和填埋两个主要途径,未能引入灵活高效的、可循环处理产生效益的处理模式。各地屈指可数的具备处理能力的特种民营企业,也因为政策扶持不够、政府配合不足,造成了亏本运作,越运作越亏本,最后纷纷倒闭或转营。 办法: 二、建议 (一)尽快完善相关法律法规。通过人大立法的形式,制定具体且可操作实施办法,清楚详细地给出生活垃圾分类指引,特别要重点标示有害垃圾的范围和种类。通过法规形式规范人们对待有害生活垃圾的行为,提高意识,形成习惯,自觉进行垃圾分类,把有害生活垃圾交由相关机构集中处理,以达到保护自然环境的目的。 (二)开展广泛的宣传动员。相关职能部门要加强宣传工作,通过电视、报纸等各种媒体多角度广泛进行生活垃圾分类宣传。同时,发动志愿者积极参与宣传活动。要让宣传活动进学校、进企业、进社区,印制和派发宣传资料,使垃圾分类处理深入人心,让大家认识到这项工作与自身生活质量息息相关,提高自觉做好垃圾分类的意识。 (三)完善生活垃圾分类设施。细化居民生活垃圾收集点的器具设置,并明确地进行标识。在公众地方、居民小区、政府企事业单位和酒店等地方,设置可回收、不可回收、有害垃圾等分类收集的垃圾箱,居民家中产生的垃圾也可用红、黄、蓝等不同颜色袋子区别分装。环卫部门收集垃圾时要分类收集转运,转运车辆也可以设置分格存放不同类别的垃圾,不能把有害垃圾进行混装收集转运。 (四)建立奖惩机制。相关法律法规应该有相应的奖励和处罚条款,在执法中做到有法可依、有法必依、执法必严、违法必究。对支持和落实有害生活垃圾分类和无害化循环

JAVA垃圾回收机制与内存泄露问题

1.垃圾收集算法的核心思想 Java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。 垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能,因此需要开发人员做比较深入的了解。 2.触发主GC(Garbage Collector)的条件 JVM进行次GC的频率很高,但因为这种GC占用时间极短,所以对系统产生的影响不大。更值得关注的是主GC的触发条件,因为它对系统影响很明显。总的来说,有两个条件会触发主GC: ①当应用程序空闲时,即没有应用线程在运行时,GC会被调用。因为GC在优先级最低的线程中进行,所以当应用忙时,GC线程就不会被调用,但以下条件除外。 ②Java堆内存不足时,GC会被调用。当应用线程在运行,并在运行过程中创建新对象,若这时内存空间不 足,JVM就会强制地调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法满足要求,则JV M将报“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回收,它们会一直占用内存。

相关主题
相关文档
最新文档