【问题标题】:A resource was acquired at attached stack trace but never released. memory leak在附加的堆栈跟踪中获取了资源,但从未释放。内存泄漏
【发布时间】:2015-07-16 05:36:03
【问题描述】:

如果我注释掉方法 (*a)->CallVoidMethod(a, b, meth, "FROM JNI"); 应用程序不会崩溃,否则它会崩溃。

假设我没有释放可能导致内存泄漏的资源“jstr”,那么为什么只有在 CallVoidMethod() 时才会发生?

我应该怎么做才能解决这个问题? 感谢所有花时间写下解决方案或阅读本文的人

错误:

android.process.acore E/StrictMode:在附加的堆栈跟踪中获取了资源,但从未释放。有关避免资源泄漏的信息,请参阅 java.io.Closeable。
java.lang.Throwable:未调用显式终止方法“关闭”

这是我的原生“C”代码...

#include "com_example_prabhu_helloworldnative_HelloWorld.h"
#include <jni.h>
#include <android/log.h>

#define  LOG_TAG    "testjni"
#define  ALOG(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

JNIEXPORT jstring JNICALL Java_com_example_prabhu_helloworldnative_HelloWorld_HelloJNI(JNIEnv *a, jobject b)
{
    //jstring jstr = (*a)->NewStringUTF(a, "This comes from jni....");
    jclass clazz =(*a)->GetObjectClass(a, b);
    jmethodID meth = (*a)->GetMethodID(a, b, "messageMe", "(Ljava/lang/String;)V");
    __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "\n this is log messge \n");
    ALOG("Hello World");
    if(meth == 0)
    {
        return;
    }

    (*a)->CallVoidMethod(a, b, meth, "FROM JNI");
    //(*a)->Release
    ALOG("REACHING HERE");

    return (*a)->NewStringUTF(a, "APXOR");
}

【问题讨论】:

    标签: java android memory-leaks android-ndk java-native-interface


    【解决方案1】:

    我认为你必须自己创建 Java 字符串:

    ...
    jstring str = env->NewStringUTF("FROM JNI");
    (*a)->CallVoidMethod(a, b, meth, str);
    env->DeleteLocalRef(str);
    ...
    

    【讨论】:

    • 试过不行所以在代码里注释了
    【解决方案2】:

    StrictMode 仅报告释放受 StrictMode 明确监控的对象的失败。它不会触发,因为您未能从 JNI 释放字符串。在堆栈跟踪指示的代码中分配的对象需要通过显式的close() 调用释放,然后再删除对它的最后引用。如果对象在关闭之前被丢弃并最终确定,系统会报错。

    您调用的方法可能与失败的对象有任何关系,也可能没有任何关系——它可能只是在执行导致 GC 更快发生的分配,因此您的应用会立即报告错误,而不是稍后再报告。

    在您的问题中包含更多的 logcat 输出可能在这里有用。严格模式代码通常配置为发出警告...如果您的应用确实崩溃,则问题可能与关闭资源失败无关。

    您的代码可能存在的一个问题是滥用b。您将它传递给GetMethodID(),它以jclass 作为第二个参数;既然这显然有效,我希望 'b' 是一个类。如果在 Java 代码中将 HelloJNI 方法声明为 static,就会出现这种情况。 (您调用GetObjectClass(a,b),但忽略结果。)在这种情况下,将'b' 作为第二个参数传递给CallVoidMethod() 可能是错误的,并且会导致失败。

    此外,如另一个答案中所述,当需要 jstring 时,您不能传递 C 字符串或 char*。 “FROM JNI”必须转换为带有NewStringUTF 的jstring。编译器应该对此发出警告。

    启用 CheckJNI 后,我预计会报告一个 JNI 错误,这会杀死应用程序。

    【讨论】:

    • 你解决了我的问题:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多