`

jna ByteBuffer的没有得到释放,导致C堆中耗尽内存

    博客分类:
  • jni
jni 
阅读更多
http://codego.net/99906/


说,我怎么JNA和Java直接拨款的理解充其量是内脏,所以我试图描述我对什么事情的理解开始。任何更正,除了反应将是巨大的... 我跑了混合了Java和C JNA本地应用程序和正在运行进行的跨与Java垃圾收集器不能自由引用的直接分配一个可重复的问题,导致了C堆耗尽 我敢肯定,我的C应用程序是不是配置问题的来源,因为我传递一个java.nio.ByteBuffer进入我的C代码 CodeGo.net,修改缓冲区中,然后在访问我的Java函数的结果。我有一个单一的malloc和一个单一的对应free每个函数调用过程中,但经过反复运行代码Java中的malloc最终将失败。 下面是一个代码轻视集,展示的问题-现实我试图拨出约在C堆函数调用时16至32MB。 我的Java代码的作用,如:
public class MyClass{
public void myfunction(){
  ByteBuffer foo = ByteBuffer.allocateDirect(1000000);
  MyDirectAccessLib.someOp(foo, 1000000);
  System.out.println(foo.get(0));
}
}
public MyDirectAccessLib{
static {
  Native.register("libsomelibrary");
}
public static native void someOp(ByteBuffer buf, int size);
}
然后,我的C代码可能是这样:
#include <stdio.h>
#include <stdlib.h>
void someOp(unsigned char* buf, int size){
unsigned char *foo;
foo = malloc(1000000);
if(!foo){
  fprintf(stderr, "Failed to malloc 1000000 bytes of memory\n");
  return;
}
free(foo);
buf[0] = 100;
}
trouble的是调用这个函数反复Java堆是稳定的(它生长缓慢),但C函数最终不能分配任何在较高的水平,我相信这就是Java是C堆中,但不清理的ByteBuffer指向在后在Java ByteBuffer的目的是比较小的。 据我发现在我的函数手动运行GC将提供所需的清理工作,但是这似乎是一个既可怜的想法,一个贫穷的解决方案。 我该如何处理这个问题更好,这样的ByteBuffer的空间被适当地释放,我的C堆空间被控制? 是我对问题的理解不正确(在那里,我跑不正确)? 编辑:缓冲区大小,以更好地反映我的实际应用,我在分配给图像约3000X2000 ...
本文地址 :CodeGo.net/99906/

-------------------------------------------------------------------------------------------------------------------------
1. 我认为你已经正确的诊断:你永远不会耗尽Java堆的,因此JVM没有垃圾收集,并且映射缓冲区不会被释放。您手动运行GC的时候没有问题,这似乎证实了这一点。你也可以打开详细日志记录集合作为一个二次确认。 所以,你可以做什么?嗯,我想尝试的优先件事是要保持初始JVM堆大小小,使用-这可能的问题 CodeGo.net,如果你的程序是不断的小分配上的Java堆,因为它会更频繁地运行GC。 我最好的PMAP工具(或任何等值是在Windows上),研究地图。这有可能是你的C堆中,通过分配可变大小的缓冲区。如果是这样的话,那么你会看到每一个大的虚拟地图,用“匿名”块之间的差距。而解决办法是分配常数大小的块是大于你所需要的。
2. 你实际上是在面临Java VM的一个已知的bug。在bug报告中列出的最佳解决方法是: “该-XX:。MaxDirectMemorySize=选项可以限制使用量来分配,将这个限制被超过一个完整的GC,从而挑起参考处理和未引用的缓冲区释放的尝试” 其他可能的解决方法包括: 偶尔插入显式System.gc()的调用,以确保直接缓冲区 减轻年轻一代的尺寸给力更频繁的GC。 明确集中直接缓冲区在应用程序级别。 如果你真的想依靠直接字节缓冲区,那么我会建议汇集在应用程序级别。根据您的应用程序,你甚至可能只是高速缓存和缓冲区(小心多线程)。
3. 我怀疑你的问题是由于直接字节缓冲区。他们可以在Java堆之外分配。 如果你频繁调用,以及分配小的缓冲区每个模式可能不是一个很好的适合直接缓冲区。 为了找出问题所在,我会切换到(Java)的堆中分配的缓冲区(该allocate替代方法allocateDirect。如果让问题消失,你已经找到了罪魁祸首。接下来的问题将是一个直接字节缓冲区是否有任何优势性能,明智的。如果不是(我猜想,事实并非如此),那么你就不需要担心如何正确清理。
4. 如果你用完的GC会自动触发。但是,如果你用完了GC的,则不会触发(在Sun的JVM,至少),你只得到一个OutOfMemoryError错误即使GC会释放我发现你必须在这种情况下手动触发GC。 一个更好的解决方案可能是对的ByteBuffer所以你永远不需要重新acllocate的ByteBuffers。
5. 要释放的直接Buffer的[1]的内存,你的JNI。 该函数GetDirectBufferAddress(JNIEnv* env, jobject buf)[3]从JNI 6的API可以获取指针的Buffer然后在标准free(void *ptr)命令上的指针自由 而不是编写如C代码从Java调用该函数,你JNA的Native.getDirectBufferPointer(Buffer)[6] 之后剩下的唯一一件事就是放弃了所有引用Buffer对象。那么Java的垃圾回收将释放Buffer例如,因为它与任何其它非引用的对象。 请注意,直接Buffer不一定映射1:1到一个区域中。例如JNI的API有NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity)[7]。因此,你应该只Buffer你知道是一对一的跟的,分配区域 我也不知道,如果你可以free直接Buffer通过Java的创建ByteBuffer.allocateDirect(int)[8]为完全如上述的理由。当交给了新的直接也可能是JVM或Java平台的具体细节是否泳池或做1:1的内存分配Buffer秒。 这里遵循从我的图书馆就直接稍加修改的片段ByteBuffer[9]处理(使用JNANative[10]和Pointer[11]类):
/**
* Allocate native memory and associate direct {@link ByteBuffer} with it.
*
* @param bytes - How many bytes of memory to allocate for the buffer
* @return The created {@link ByteBuffer}.
*/
public static ByteBuffer allocateByteBuffer(int bytes) {
  long lPtr = Native.malloc(bytes);
  if (lPtr == 0) throw new Error(
   "Failed to allocate direct byte buffer memory");
  return Native.getDirectByteBuffer(lPtr, bytes);
}
/**
* Free native memory inside {@link Buffer}.
* <p>
* Use only buffers whose memory region you know to match one to one
* with that of the underlying allocated memory region.
*
* @param buffer - Buffer whose native memory is to be freed.
* The class instance will remain. Don't use it anymore.
*/
public static void freeNativeBufferMemory(Buffer buffer) {
  buffer.clear();
  Pointer javaPointer = Native.getDirectBufferPointer(buffer);
  long lPtr = Pointer.nativeValue(javaPointer);
  Native.free(lPtr);
}
分享到:
评论

相关推荐

    使用JNA替代JNI调用DLL,并解决内存溢出问题

    ### 使用JNA替代JNI调用DLL,并解决内存溢出问题 #### 问题背景 在项目的开发过程中,常常遇到需要处理二进制流数据并对其进行解析处理的情况。这种情况下,如果上层应用平台采用的是Java开发,而底层算法或数据...

    深入解析JNA—模拟C语言结构体

    通过上述方法,我们可以在Java中有效地模拟C语言的结构体,并利用JNA与本地C/C++库进行交互。这对于需要跨语言调用的应用场景非常有用,尤其是当目标平台提供了丰富的C/C++库时。此外,这种方法还提高了代码的可维护...

    jna.rar_jna_jna.jar_jna文件

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码无需编写本地代码(如C/C++)即可直接调用操作系统级别的API。JNA通过动态链接库(DLLs on Windows,shared libraries on Unix/Linux)实现了这...

    java通过jna返回结构体例子.rar

    Java通过JNA(Java Native Access)与C语言交互是一种常见的技术,特别是在需要访问操作系统底层功能或利用已有的C库时。本示例是关于如何在Java中使用JNA处理C语言返回的结构体数据。下面将详细介绍这个过程,以及...

    jna整合包-jna4.5.0+jna4.0.0.rar

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码直接调用操作系统提供的原生函数,而无需编写任何C/C++代码或使用JNI(Java Native Interface)。JNA通过提供一种映射机制,将Java方法与本地库...

    jna-5.0.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    jna-5.6.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    利用jna在java下调用c语言库文件

    本示例将详细解析如何使用JNA在Java中调用C语言库文件。 首先,我们需要理解JNA的工作原理。JNA通过映射Java方法到本地函数来实现调用,这得益于其内建的类型映射系统。Java中的数据类型会自动转换为对应的C语言...

    Android通过JNA调用C,C++方法

    本篇文章将详细讲解如何在Android中使用JNA来调用C/C++方法。 首先,了解JNA的基本概念。JNA是一种轻量级的Java库,它允许Java程序直接调用动态链接库(DLL)或共享库(SO)中的函数,无需编写JNI代码。相比之下,...

    jna-5.4.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    jna-4.4.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    jna3.2.1.rar

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码直接调用操作系统提供的原生函数,而无需编写C/C++的中间层,极大地简化了Java与本地操作系统接口的交互。JNA 3.2.1是该库的一个版本,提供了对...

    jna-3.0.9.jar和examples.jar

    标题中的"jna-3.0.9.jar和examples.jar"是两个重要的Java类库文件,它们在IT领域,特别是Java开发中具有显著的应用价值。JNA(Java Native Access)是一个开源项目,它提供了一种方便的方式来调用本地库(如C、C++...

    JNA 调用dll jna调用 c++

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码直接调用操作系统提供的原生函数,而无需编写C语言的中间接口(JNI)。JNA通过映射Java方法到本地库中的函数,实现了Java与C/C++等本地代码的...

    jna-4.5.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    jna-5.10.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    JNA 4.1.0 官方版

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码直接调用操作系统提供的原生函数,而无需编写C语言的JNI(Java Native Interface)代码。JNA 4.1.0是该库的一个官方版本,提供了增强的功能和...

    jna-5.5.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    jna-4.0.0.jar中文文档.zip

    注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt...

    JNA所需要的jar包

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码与本地操作系统API进行交互,无需编写C代码或使用Java Native Interface (JNI)。JNA通过提供一种高级接口,让开发者能够轻松地调用本地库函数,...

Global site tag (gtag.js) - Google Analytics