深入浅出Java堆的管理

引言

java的堆是一个运行时数据区,类的实例(对象)从中分配空间。java虚拟机(jvm)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。一般来说,堆的是由垃圾回收来负责的,尽管jvm规范并不要求特殊的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,jvm在实现的时候都有一个由垃圾回收所管理的堆。垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。

垃圾收集的意义

在c中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。jvm的一个系统级线程会自动释放该内存块。垃圾收集意味着程序不再需要的对象是无用信息,这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。事实上,除了释放没用的对象,垃圾收集也可以清除内存记录碎片。由于创建对象和垃圾收集器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆的一端,jvm将整理出的内存分配给新的对象。

垃圾收集能自动释放内存空间,减轻编程的负担。这使java虚拟机具有一些优点。首先,它能使编程效率提高。在没有垃圾收集机制的时候,可能要花许多时间来解决一个难懂的存储器问题。在用java语言编程的时候,靠垃圾收集机制可大大缩短时间。其次是它保护程序的完整性,垃圾收集是java语言安全性策略的一个重要部份。

垃圾收集的一个潜在的缺点是它的开销影响程序性能。java虚拟机必须追踪运行程序中有用的对象,而且最终释放没用的对象。这一个过程需要花费处理器的时间。其次垃圾收集算法的不完备性,早先采用的某些垃圾收集算法就不能保证100%收集到所有的废弃内存。当然随着垃圾收集算法的不断改进以及软硬件运行效率的不断提升,这些问题都可以迎刃而解。

垃圾收集的算法分析

java语言规范没有明确地说明jvm使用哪种垃圾回收算法,但是任何一种垃圾收集算法一般要做2件基本的事情:(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。

大多数垃圾回收算法使用了根集(rootset)这个概念;所谓根集就量正在执行的java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。垃圾收集首选需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。而根集通过任意路径不可达的对象符合垃圾收集的条件,应该被回收。下面介绍几个常用的算法。

1、引用计数法(reference counting collector)

引用计数法是唯一没有使用根集的垃圾回收得法,该算法使用引用计数器来区分存活对象和不再使用的对象。一般来说,堆中的每个对象对应一个引用计数器。当每一次创建一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意变量时,引用计数器每次加1。当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。

基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜地必须实时运行的程序。但引用计数器增加了程序执行的开销,因为每次对象赋给新的变量,计数器加1,而每次现有对象出了作用域生,计数器减1。

时间: 2024-08-25 15:52:03

深入浅出Java堆的管理的相关文章

深入浅出谈垃圾的回收—Java堆的管理

Java的堆是一个运行时数据区,类的实例(对象)从中分配空间.Java虚拟机(Jvm)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new.newarray.anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式的释放.一般来说,堆是由垃圾回收来负责的,尽管Jvm规范并不要求特殊的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,Jvm在实现的时候都有一个由垃圾回收所管理的堆.垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的

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

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

《JVM故障诊断指南》之2 —— 调整合适的Java堆大小的技巧

原文链接 原文作者:Byron Kiourtzoglou 翻译:梅小西(904516706) 在生产系统上决定合适的Java堆大小不是一个容易的操作.许多性能问题的发生都是由于不恰当的Java堆容量的错误调整.这部分将从介绍一些技巧作为开头,它能帮助你在当前的或者新的生产系统上决定最佳的Java堆大小.其中一些技巧对预防OutOfMemoryError问题和内存泄露方面也同样有用. 请注意这些技巧是倾向于"帮助你"决定合适的Java堆大小.因为每一个IT环境都不相同,实际上你是处于最好

关于c++堆栈与java堆的区别

问题描述 关于c++堆栈与java堆的区别 最近看java编程思想 看到这样一句话:"在Java中,所有对象都必须在内存"堆"里创建.而在C++中,对象是在堆栈中创建的.这样可达到更快的速度,"这句话不能理解.c++的堆栈和java的堆有啥区别啊. PS:原文"最重要的一种情况是C和C++对内存的管理方式,它是某些人觉得Java速度肯定慢的重要依据:在Java中,所有对象都必须在内存"堆"里创建.而在C++中,对象是在堆栈中创建的.这样

Java自动内存管理详解

最近找了两本Java虚拟机方面的书,看了看其中对于Java自动内存管理的章节,写的都大同小异,在此总结一下,主要是三个方面:内存划分.内存分配.内存回收. 内存划分(运行时数据区) JVM运行时数据区 从线程的角度来分,可分为线程私有和线程共享的,上图中左边的灰色区域就是线程共享的区域,包括堆.方法区.运行时常量池.而右边的区域则是线程私有的,包括程序计数器.虚拟机栈. 堆 堆是虚拟机管理的内存中最大的一块,是被线程共享的一块区域,主要用于存放对象实例,但并不是所有对象都是在堆上分配的.同时堆也

Java堆内存

  Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象.   在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ( Young ) 又被划分为三个区域:Eden.From Survivor.To Survivor.   这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收.   堆的内存模型大致为:   新生代:Young Generation,主要用来存放新生的对象.   老

哪个更快:Java堆还是本地内存

使用Java的一个好处就是你可以不用亲自来管理内存的分配和释放.当你用new关键字来实例化一个对象时,它所需的内存会自动的在Java堆中分配.堆会被垃圾回收器进行管理,并且它会在对象超出作用域时进行内存回收.但是在JVM中有一个'后门'可以让你访问不在堆中的本地内存(native memory).在这篇文章中,我会给你演示一个对象是怎样以连续的字节码的方式在内存中进行存储,并且告诉你是应该怎样存储这些字节,是在Java堆中还是在本地内存中.最后我会就怎样从JVM中访问内存更快给一些结论:是用Ja

通过IBM eXtremeMemory实现超越Java堆的弹性缓存

因为 eXtremeMemory 位于 Java 虚拟机 (JVM) 环境之外,所以我们开发了一种名为 IBM eXtremeIO 的新传输方式,用它来提高 eXtremeMemory 弹性缓存的容错能力.eXtremeIO 实现了 http://www.aliyun.com/zixun/aggregation/13387.html">WebSphere eXtreme Scale 容器之间高效的内存到内存复制.本文将概述 eXtremeMemory 和 eXtremeIO 功能. IBM

从Java代码到Java堆

优化应用程序代码的内存使用并不是一个新主题,但是人们通常并没有很好地理解这个主题.本文将简要介绍 Java 进 程的内存使用,随后深入探讨您编写的 Java 代码的内存使用.最后,本文将展示提高代码内存效率的方法,特别强调了 HashMap 和 ArrayList 等 Java 集合的使用. 背景信息:Java 进程的内存使用 通过在命令行中执行 java 或者启动某种基于 Java 的中间件来运行 Java 应用程序时,Java 运行时会创建一个操作系统进程,就像您运行基于 C 的 程序时那样