(转)在JNI编程中避免内存泄漏

    本文转自:http://www.ibm.com/developerworks/cn/java/j-lo-jnileak/index.html
    简介: 本文详细论述如何在 JNI 编程中避免内存泄漏。论述了 JNI 编程中可能引发的明显的内存泄漏。本文的重点是阐述 JNI 编程中潜在的内存泄漏,希望读者通过本文对 Local reference 有更深刻的理解,了解 Local reference 表的存在,区分 Local reference 和局部变量,从而认识到 Local reference 可能引发的 native memory 内存泄漏。

    JNI 编程简介
    JNI,Java Native Interface,是 native code 的编程接口。JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native code;在 native code 中嵌入 Java 虚拟机调用 Java 的代码。
    JNI 编程在软件开发中运用广泛,其优势可以归结为以下几点:

  1. 利用 native code 的平台相关性,在平台相关的编程中彰显优势。
  2. 对 native code 的代码重用。
  3. native code 底层操作,更加高效。
     

    然而任何事物都具有两面性,JNI 编程也同样如此。程序员在使用 JNI 时应当认识到 JNI 编程中如下的几点弊端,扬长避短,才可以写出更加完善、高性能的代码:

  1. 从 Java 环境到 native code 的上下文切换耗时、低效。
  2. JNI 编程,如果操作不当,可能引起 Java 虚拟机的崩溃。
  3. JNI 编程,如果操作不当,可能引起内存泄漏。

    JAVA 中的内存泄漏

    JAVA 编程中的内存泄漏,从泄漏的内存位置角度可以分为两种:JVM 中 Java Heap 的内存泄漏;JVM 内存中 native memory 的内存泄漏。

    Java Heap 的内存泄漏

    Java 对象存储在 JVM 进程空间中的 Java Heap 中,Java Heap 可以在 JVM 运行过程中动态变化。如果 Java 对象越来越多,占据 Java Heap 的空间也越来越大,JVM 会在运行时扩充 Java Heap 的容量。如果 Java Heap 容量扩充到上限,并且在 GC 后仍然没有足够空间分配新的 Java 对象,便会抛出 out of memory 异常,导致 JVM 进程崩溃。
    Java Heap 中 out of memory 异常的出现有两种原因——①程序过于庞大,致使过多 Java 对象的同时存在;②程序编写的错误导致 Java Heap 内存泄漏。
    多种原因可能导致 Java Heap 内存泄漏。JNI 编程错误也可能导致 Java Heap 的内存泄漏。

    JVM 中 native memory 的内存泄漏

    从操作系统角度看,JVM 在运行时和其它进程没有本质区别。在系统级别上,它们具有同样的调度机制,同样的内存分配方式,同样的内存格局。
    JVM 进程空间中,Java Heap 以外的内存空间称为 JVM 的 native memory。进程的很多资源都是存储在 JVM 的 native memory 中,例如载入的代码映像,线程的堆栈,线程的管理控制块,JVM 的静态数据、全局数据等等。也包括 JNI 程序中 native code 分配到的资源。
    在 JVM 运行中,多数进程资源从 native memory 中动态分配。当越来越多的资源在 native memory 中分配,占据越来越多 native memory 空间并且达到 native memory 上限时,JVM 会抛出异常,使 JVM 进程异常退出。而此时 Java Heap 往往还没有达到上限。
    多种原因可能导致 JVM 的 native memory 内存泄漏。例如 JVM 在运行中过多的线程被创建,并且在同时运行。JVM 为线程分配的资源就可能耗尽 native memory 的容量。
    JNI 编程错误也可能导致 native memory 的内存泄漏。对这个话题的讨论是本文的重点。

继续阅读“(转)在JNI编程中避免内存泄漏”