在Java应用系统开发中如何避免Java程序出现内存泄漏

发布时间:2021-09-17 18:13:01

在Java应用系统开发中 如何避免Java程序出现内存泄漏 1、程序开发人员必须有效地管理程序中所申请的内存空间 (1)动态内存分配 所谓动态内存分配(Dynamic Memory Allocation)就是 指在程序执行的过程中动态地分配或者回收存储空间的分配内 存的方法。 比如在程 序中采用new 创建对象实例 就是一个典型 的动态内存分 配的应用示例。 右图为 Java程序在执 行过程中的系 统内存应用的 状况示图。 (2)在程序编程开发实现中需要有效地管理相关的内存空间 1)在编程时进行动态内存分配是非常必要的。它可以在程序 运行的过程中帮助分配所需的内存,而不是在进程启动的时 候就进行分配(静态内存分配,如数组定义)。 2)然而,有效地管理这些内存同样也是非常重要的,否则将 导致程序在运行过程中出现内存泄露。 右边 图示中的 Java程序代 码在运行过 程中将会导 致内存泄漏 (溢出)。 2、Java语言和C++语言在内存管理方面的差别 (1)C++语言的内存管理机制 1)在C++语言的程序开发实现中,如果程序需要动态分配一块 内存区域,程序开发人员需要负责这块内存的整个生命周期 的控制——从申请分配、到使用、再到最后的释放的整个过 程。 2)这样的过程尽管给予程序员极大的灵活性,但是却十分繁 琐,程序员很容易由于疏忽而忘记释放相关的内存,从而导 致系统或者程序所在的内存出现泄露现象。 (2)Java语言的内存管 理机制 1)Java语言由于对 内存管理做了自己 的优化,这就是垃 圾回收机制。 2)Java程序中所涉及的内存使用相关的内存对象基本上都是 在堆(Heap)内存上分配(基本数据类型除外),然后由垃 圾回收器GC(Garbage Collection)负责自动回收程序中不 再使用的内存空间。 3)因此,在Java程序中的内存空间的分配是由开发人员在程 序中通过申请而完成的,而对所申请的相关内存的释放则是 由垃圾回收器GC完成的,这种“收”和“支”相分离的两条 线的方法确实简化了程序员的工作。但同时,它也加重了 Java虚拟机(JVM)的工作负担。 3、垃圾回收器GC回收内存对象的策略 (1)Java程序中对内存对象的访问采用引用方式 1)在Java代码中,开发人员需要维护一个内存对象的引用变 量,通过这个引用变量的值,开发人员可以访问到对应的内 存地址中的内存对象空间。 2)垃圾回收器GC线会从程序代码栈中的引用变量开始跟踪, 从而判定哪些内存是正在使用的。 3)如果垃圾回收器GC线程通过这种方式,无法跟踪到某一块 堆内存,那么垃圾回收器GC就认为这块内存将不再使用了 (因为代码中已经无法访问到这块内存了)。 (2)Java程序中所涉及的内存是托管的 1)也就是由系统来管理对象。系统对每个对象都会有监听— —监视对象状态是为了更加准确地、及时地释放对象,所以 首先不要创建过多的对象,这样可以避免系统对那些无用对 象的监听。 2)这也是Java程序运行速度较慢的原因之一,因为垃圾回收 器GC为了能够正确释放对象,垃圾回收器GC必须监控每一 个对象的运行状态,包括对象的申请、引用、被引用、赋值 等,垃圾回收器GC都需要进行监控。 (3)垃圾回收器GC回收内存对象的策略 当一个内存对象失去了所有的引用之后,垃圾回收器GC就 可以将其回收。反过来说,如果这个对象还存在引用,那么它 将不会被垃圾回收器GC回收。 4、什么是内存泄露(Memory Leak) (1)内存泄露 1)当以前分配的一片内存不再需要使用或无法访问时,但是却 并没有释放它,那么对于该进程来说,会因此导致总可用内 存的减少,这时就出现了内存泄漏,JVM将会抛出 java.lang.OutOfMemoryError的异常。 2)内存泄漏并非指内存在物理上的消失,而是应用程序分配某 段内存后,由于设计错误,失去了对该段内存的控制,因而 造成了内存的浪费。 (2)存在内存泄露的程序对象的两个主要的特点 对象仍然被引用但却是无用的,即程序以后不会再使用这 些对象。如果对象满足这两个条件,这些对象就可以判定为 Java中的内存泄漏,这些对象不会被垃圾回收器GC所回收,然 而它却占用内存。 (3)Java也存在内存泄露,但它的表现与C++不同。 5、程序编程开发实现中内存泄漏的主要分类 (1)常发性内存泄漏 发生内存泄漏的代码会被多次执行到,每次被执行的时候 都会导致一块内存泄漏。 (2)偶发性内存泄漏 1)发生内存泄漏的代码只有在某些特定环境或操作过程下才 会发生。常发性和偶发性是相对的。对于特定的环境,偶发 性的也许就变成了常发性的。 2)所以测试环境和测试方法对检测内存泄漏至关重要。 (3)一次性内存泄漏 1)发生内存泄漏的代码只会被执行一次,或者由于算法上的 缺陷,导致总会有一块且仅一块内存发生泄漏。 2)比如,在一个单例(Singleton)程序类的构造函数中分配 内存,而在析构函数中却没有释放该内存。而Singleton程 序类只存在一个实例,所以内存泄漏只会发生一次。 (4)隐式内存泄漏 1)程序在运行过程中不停地进行分配内存,但是直到结束的时 候才释放内存。严格的说这里并没有发生内存泄漏,因为最 终程序释放了所有申请的内存。 2)但是如果对于一个服务器端的程序发生这样的“问题”,由 于服务器端程序需要运行几天、几周甚至几个月或者一直在 运行,不及时地释放相关的无用内存也可能导致最终耗尽系 统的所有内存空间。所以,这类内存泄漏属于隐式内存泄 漏——不易及时发现。 6、Java程序出现内存泄露的场合及代码示例 (1)内存泄漏的两种场合 1)一种情况是在堆中的分配的内存,在没有将其释放掉的时候, 就将所有能访问这块内存的方式都删掉(如指针重新赋值), 将导致该内存块将不能再被访问——对象被分配了内存空间 却不可使用; 2)另一种情况则是在内存对象明明已经不需要的时候,还仍然 保留着这

相关文档

  • 关于JAVA应用程序中的内存泄漏研究
  • 建立Java应用程序框架降低Java信息系统开发难度
  • 清剿Java程序中的内存泄漏
  • 猜你喜欢

    电脑版