java语言 百分网手机站

Java 语言与C语言中垃圾回收的不同方式

时间:2020-09-04 09:39:57 java语言 我要投稿

Java 语言与C语言中垃圾回收的不同方式

  导语:垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾回收算法来实现资源自动回收。下面就由小编为大家介绍一下Java 语言与C语言中垃圾回收的不同方式,欢迎大家阅读!

Java 语言与C语言中垃圾回收的不同方式

  1 Java语言中的垃圾回收机制

  时下最流行的编程语言Java拥有自己的垃圾回收机制。实际上,Java语言来自于C++语言。但Java语言避免了C++语言中复杂的结构,成功克服了多重继承机制存在的二义性问题;Java的垃圾回收机制显著地提高了程序的效率,降低了复杂度。由于有垃圾回收机制,使Java中的对象不再有“作用域”的概念,而只有对象的引用才有“作用域”。垃圾回收器是一种动态存储分配器,它自动释放程序不再需要的已分配堆块,并且能够压缩进程堆块所需要的内存空间。垃圾收集是指自动回收不被程序占用的分配堆块的过程。在一个支持垃圾收集的系统中,应用显式分配堆块,但是从不显式释放堆块。垃圾回收器一般是作为一个低级别的独立线程运行,不可预知的情况下对内存堆中已经废除的'或者长时间没有使用的对象进行清除和回收,而程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。

  Java编程人员不用担心内存管理,垃圾收集器会自动进行管理。但是垃圾回收机制通常只在满足两个条件时才运行:即有对象要求回收并且系统需要回收。那么,Java的垃圾回收机制是如何操作的呢?下面我们来了解一下Java垃圾回收机制的算法。

  1.1 引用计数法

  引用计数法,是最原始也是被很多语言所广泛应用的垃圾回收算法。其主旨是给堆中每一个对象都设置一个引用计数,当其被赋值给对象的引用时,其引用计数加1,当其对象的引用超出生命周期或者被新值赋值时,引用减1,当其引用计数为0时,即可被系统回收。

  1.2 跟踪算法

  引用计数法一种重要的问题在于当对象间出现循环引用的时候,其计数永远不会为0,既永远不会被回收。跟踪算法解决了这一问题,跟踪算法是采用从根集开始扫描来识别对象是否可达。标记可达的对象,将不可达的对象也就是未标记的对象清除,又称标记和清除算法。

  1.3 压缩算法

  跟踪算法的一个问题就是清除对象后的内存空间变成了堆碎片,不便于再次利用。为了解决这个问题,引入了压缩算法。所谓压缩算法就是在清除的过程中,将所有对象移动到堆的一端,而本来的那端就变成了一段空闲内存区,收集器要对移动对象的所有引用进行更新。

  1.4 复制算法

  压缩算法的问题在于每次对对象引用更新的时候都产生了冗余的句柄和句柄表。为此,又引入了复制算法,复制算法的主旨是在一开始就把堆分成一个对象面和多个空闲面,将对象面的内存空间分配给程序,当空间满了的时候,利用追踪算法的机理扫描活动对象,但并不清除,而是将每个活动对象复制到空闲面,这样空闲面和对象面就互换了。

  1.5 分代算法

  复制算法又称停止和复制算法,在其对象面和空闲面切换的过程中程序要暂停执行,这样大大降低了程序执行的效率。分代算法正好可以解决这个问题。分代算法基于程序中大多数对象生命周期较短,少数较长的特点,将堆分成多个,每个子堆作为对象的一代。垃圾收集器从最新创建的对象中,将活跃的对象移到最高代的子堆中,这样老一代的子堆不会被经常回收,利用这种分代式的方法,节约了时间。

  1.6 自适应算法

  自适应法,就是指根据特殊情况,采取特殊算法,通过监控当前堆的使用情况选择适当的算法进行垃圾回收。

  垃圾回收要占用时间,因此,Java运行时,系统只在需要的时候才使用它,而编程者本身无法知道回收发生的准确时间。但如果需要垃圾回收,编程者也可以随时调用下面的方法之一:

  System.gc();

  Runtime.getRuntime().gc();

  2 C语言中的垃圾回收

  C语言凭借其简洁紧凑、数据类型丰富、程序执行效率高等特点,拥有着大量的编程爱好者,而众多IT界牛人也说,精通C语言,就等于精通编程。然而C语言实际上是没有垃圾回收机制的,那么被如此广泛应用的编程语言如何来处理其垃圾回收问题呢?

  答案就是使用保守垃圾收集器并调用free()函数。像Java语言中,垃圾收集器对于指针的创建和使用有着严格的控制,所以其能回收所有的垃圾内存,而诸如C这样的语言,垃圾收集器不能被严格控制,则称之为保守垃圾收集器。

  那么在C语言中的垃圾收集器是如何工作的呢?

  C语言支持垃圾回收系统,如前文所说,在支持垃圾收集的系统中,应用显示分配堆块,但不显式地释放。而在C语言程序中,应用程序调用malloc()函数但是从不调用free()函数,取而代之的是使用垃圾收集器周期性识别垃圾堆块,并需要编程人员调用free()函数,将这些垃圾堆块放回到空闲链表中。因此,只依靠垃圾收集器是无法做到垃圾内存的全部释放。

  下面我们用有向图的概念理解存储器,当存在一条从任意根节点出发并到达Q点的有向路径时,我们说节点Q是可达的。Java语言中的垃圾回收器,能够准确的标记每个节点是否可达,并将不可达的节点回收,放入空链表中。而C语言的垃圾回收器,就是我们所说的保守垃圾回收器,能够正确地标记可达的节点,但一些不可达的节点却有可能被错误地标记为可达。从而,被错误标记的节点,将永远不会被回收。可想而知,当系统中的内存被错误标记所占满时,系统将无法再运行。

  下面我们来看,垃圾收集器如何为C程序将一个保守的收集器加入到已存在的malloc()函数中,如图1所示。

  垃圾收集器作为一个应用并行的独立线程,不断地更新有向图和回收垃圾。无论应用程序何时需要内存空间,系统都会调用malloc()函数,如果malloc()函数找不到可用的内存分配快,那么它就调用垃圾收集器,垃圾收集器识别出垃圾块,并通过调用free()函数将它们返回给堆块。这里的关键在于,垃圾收集器代替了应用程序去调用free()函数,当对垃圾收集的调用返回时,malloc()函数想要发现一个可用的空闲块。如果还是不成功,它就向操作系统请求额外的存储器。最后,如果成功,malloc()函数返回一个指向请求块的指针,如果不成功就返回一个空指针。

  3 小结

  综上所述,不同语言对于垃圾回收的方式不同,但是不管是什么语言,垃圾回收都有着重要的作用。所以,在编程学习中,尤其是编程入门阶段应该养成调用内存释放函数的好习惯,在每次占用内存结束后,应主动释放内存,这样即节省内存空间,又提高系统效率。

【Java 语言与C语言中垃圾回收的不同方式】相关文章:

C语言中函数之间地址传递方式09-27

在C语言中函数调用方式的区别11-20

C语言与JAVA理论区别10-06

c语言中怎么画图10-07

C语言中assert用法10-03

深入解析C语言中的数值与真假11-21

C语言中指针与数组的区别10-05

C语言中的运算规则10-08

C语言中的字符(char)10-07

C语言中的链接编写10-07