当前位置: 首页 > 面试题库 >

JNI Attach / Detach线程内存管理

梅逸清
2023-03-14
问题内容

我有一个JNI回调:

void callback(Data *data, char *callbackName){
    JNIEnv *env;
    jvm->AttachCurrentThread((void **)&env, NULL);
    /* start useful code*/

    /* end useful code */
    jvm->DetachCurrentThread();
}

当我像这样(空有用的代码)运行它时,会发生内存泄漏。如果我注释掉整个方法,则不会泄漏。连接/分离线程的正确方法是什么?

我的应用程序处理实时声音数据,因此负责数据处理的线程必须尽快完成,以便为下一批做好准备。因此,对于这些回调,我创建了新线程。每秒有数十个甚至数百个它们,它们将自己附加到JVM,调用一个回调函数来重绘图形,分离并消亡。这是做这些事情的正确方法吗?如何处理内存泄漏?

编辑:错别字

好的,我创建了一个最少的代码:

package test;

public class Start
{
    public static void main(String[] args) throws InterruptedException{
        System.loadLibrary("Debug/JNITest");
        start();
    }

    public static native void start();
}

#include <jni.h>
#include <Windows.h>
#include "test_Start.h"

JavaVM *jvm;
DWORD WINAPI attach(__in  LPVOID lpParameter);

JNIEXPORT void JNICALL Java_test_Start_start(JNIEnv *env, jclass){
    env->GetJavaVM(&jvm);
    while(true){
        CreateThread(NULL, 0, &(attach), NULL, 0, NULL);
        Sleep(10);
    }
}


DWORD WINAPI attach(__in  LPVOID lpParameter){
    JNIEnv *env;
    jvm->AttachCurrentThread((void **)&env, NULL);
    jvm->DetachCurrentThread();
    return 0;
}

当我运行VisualJM探查器时,我得到了通常的锯齿模式,那里没有泄漏。堆使用量达到5MB左右的峰值。但是,观察进程浏览器确实显示出一些奇怪的行为:内存正在缓慢地上升和上升,在一分钟左右的时间内每秒4K,然后突然所有分配的内存下降。这些丢弃与垃圾回收不对应(它们比发生探查器中的锯齿出现的频率更低,分配的内存更少)。

因此,我最好的选择是这是某些OS行为处理成千上万毫秒的线程。某些大师对此有解释吗?


问题答案:

我发现了问题。它在JNI代码I中悬挂着本地引用

没有破坏。每个回调都会创建一个新的本地引用,因此导致内存泄漏。当我将本地引用转换为全局引用时,所以我可以重复使用,问题就消失了



 类似资料:
  • 对于一个基于图论的框架来说,节点和边是最小的部件。实际应用中,这些部件构成了各种有向图。比如一个有环图,它的数据流动就是一个环形,部件之间的持有关系如果不能很好的处理,那么可能就会存在内存问题。EasyReact 的内存管理逻辑非常简单,也非常精巧。可以让框架使用者无需关注太多的细节即可轻松的使用,而不必担心本框架涉及的内存方面的问题。 中间节点 节点包含了 fork、map、filter、ski

  • 在计算系统中,通常存储空间可以分为两种:内部存储空间和外部存储空间。内部存储空间通常访问速度比较快,能够按照变量地址随机地访问,也就是我们通常所说的 RAM(随机存储器),可以把它理解为电脑的内存;而外部存储空间内所保存的内容相对来说比较固定,即使掉电后数据也不会丢失,这就是通常所讲的 ROM(只读存储器),可以把它理解为电脑的硬盘。 计算机系统中,变量、中间数据一般存放在 RAM 中,只有在实际

  • 内存生命周期 垃圾回收 垃圾回收在计算机科学中是一种自动的内存管理机制。当一个计算机上的动态内存不再需要时,就应该予以释放以让出内存,这种内存资源管理称为垃圾回收。垃圾回收器可以让程序员减轻许多负担,也减少程序员犯错的机会。 特征 垃圾回收基于两个原理: 考虑某个对象在未来的程序运行中将不会被访问; 向这些对象要求归还内存。 然而,最主要的也是最艰难的部分就是找到「所分配的内存确实已经不再需要了」

  • 主要内容:一、redis的内存管理,二、源码分析,三、总结一、redis的内存管理 一般来说,稍微有点规模的软件,都会自己搞一块内存管理,原因很简单,统一管理内存,适应自己的场景。其实按大牛们的话,这未必是最优选择,实在是小看了写库的那群大牛们。不过说归说,人家写也不会给你报备,想写自然就写了。Redis就听从了大牛的看法,使用了底层更好的内存分配库,根据情况使用tmalloc,jemalloc 以及glibc中的 malloc(pmalloc)。 一般

  • 本章描述 Linux 内核中的内存管理。在本章中你会看到一系列描述 Linux 内核内存管理框架的不同部分的帖子。 内存块 - 描述早期的 memblock 分配器。 固定映射地址和 ioremap - 描述固定映射的地址和早期的 ioremap 。 kmemcheck - 第三部分描述 kmemcheck 工具。

  • 问题内容: 我需要监视应用程序产生的线程消耗的内存量。如果贪婪的线程消耗太多内存,则想法是采取纠正措施。我已提到Java线程占用多少内存?。关于该链接的建议之一是在我尝试以下工作时使用。 我在四个线程上运行了很长时间。尽管作业不会连续地累积内存,但是所返回的值会不断增加,甚至不会下降。这意味着不会返回线程使用的堆上的实际内存量。它返回自线程启动以来在堆上为线程分配的内存总量。我的平台详细信息如下: