简体   繁体   English

Android JNI:java.lang.UnsatisfiedLinkError

[英]Android JNI : java.lang.UnsatisfiedLinkError

I am writing a code to clear a native heap which increase my native heap results into out of memory error.thus i am writing a code using android ndk but it gives java.lang.UnsatisfiedLinkError 我正在编写代码以清除本机堆,这会增加本机堆结果进入内存不足错误。因此,我正在使用android ndk编写代码,但它给出了java.lang.UnsatisfiedLinkError

here is my code 这是我的代码

android.mk android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := sounds_english
LOCAL_SRC_FILES := JniBitmapStorageTest.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics

include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g

JniBitmapStorageTest.cpp JniBitmapStorageTest.cpp

#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>


#define  LOG_TAG    "DEBUG"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

extern "C"
  {
  JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);
  JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);
  JNIEXPORT void JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);
  }

class JniBitmap
  {
  public:
    uint32_t* _storedBitmapPixels;
    AndroidBitmapInfo _bitmapInfo;
    JniBitmap()
      {
      _storedBitmapPixels = NULL;
      }
  };

JNIEXPORT void JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)
  {
  JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
  if (jniBitmap->_storedBitmapPixels == NULL)
    return;
  delete[] jniBitmap->_storedBitmapPixels;
  jniBitmap->_storedBitmapPixels = NULL;
  delete jniBitmap;
  }

JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle)
  {
  JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
  if (jniBitmap->_storedBitmapPixels == NULL)
    {
    LOGD("no bitmap data was stored. returning null...");
    return NULL;
    }
  //
  //creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) :
  //
  //LOGD("creating new bitmap...");
  jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
  jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
  jstring configName = env->NewStringUTF("ARGB_8888");
  jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
  jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
  jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName);
  jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.height, jniBitmap->_bitmapInfo.width, bitmapConfig);
  //
  // putting the pixels into the new bitmap:
  //
  int ret;
  void* bitmapPixels;
  if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0)
    {
    LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    return NULL;
    }
  uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;
  int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width;
  memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount);
  AndroidBitmap_unlockPixels(env, newBitmap);
  //LOGD("returning the new bitmap");
  return newBitmap;
  }

JNIEXPORT jobject JNICALL Java_com_example_sounds_english_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap)
  {
  AndroidBitmapInfo bitmapInfo;
  uint32_t* storedBitmapPixels = NULL;
  //LOGD("reading bitmap info...");
  int ret;
  if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)
    {
    LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
    return NULL;
    }
  LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride);
  if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
    {
    LOGE("Bitmap format is not RGBA_8888!");
    return NULL;
    }
  //
  //read pixels of bitmap into native memory :
  //
  //LOGD("reading bitmap pixels...");
  void* bitmapPixels;
  if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0)
    {
    LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    return NULL;
    }
  uint32_t* src = (uint32_t*) bitmapPixels;
  storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
  int pixelsCount = bitmapInfo.height * bitmapInfo.width;
  memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount);
  AndroidBitmap_unlockPixels(env, bitmap);
  JniBitmap *jniBitmap = new JniBitmap();
  jniBitmap->_bitmapInfo = bitmapInfo;
  jniBitmap->_storedBitmapPixels = storedBitmapPixels;
  return env->NewDirectByteBuffer(jniBitmap, 0);
  }

JniBitmapHolder.java JniBitmapHolder.java

package com.example.sounds_english;

import java.nio.ByteBuffer;

import android.graphics.Bitmap;
import android.util.Log;

public class JniBitmapHolder
{
      ByteBuffer _handler =null;
      static
        {
        System.loadLibrary("sounds_english");
        }

      private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);

      private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);

      private native void jniFreeBitmapData(ByteBuffer handler);

      public JniBitmapHolder()
        {}

      public JniBitmapHolder(final Bitmap bitmap)
        {
        storeBitmap(bitmap);
        }

      public void storeBitmap(final Bitmap bitmap)
        {
        if(_handler!=null)
          freeBitmap();
        _handler=jniStoreBitmapData(bitmap);
        }

      public Bitmap getBitmap()
        {
        if(_handler==null)
          return null;
        return jniGetBitmapFromStoredBitmapData(_handler);
        }

      public Bitmap getBitmapAndFree()
        {
        final Bitmap bitmap=getBitmap();
        freeBitmap();
        return bitmap;
        }

      public void freeBitmap()
        {
        if(_handler==null)
          return;
        jniFreeBitmapData(_handler);
        _handler=null;
        }

      @Override
      protected void finalize() throws Throwable
        {
        super.finalize();
        if(_handler==null)
          return;
        Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can");
        freeBitmap();
        }
      }

myactivity.java myactivity.java

      aa=p2.getWordimage();
                        aa1=decodeSampledBitmapFromResource(aa);
                        final JniBitmapHolder bitmapHolder=new   JniBitmapHolder(aa1);
                        aa1.recycle();


                        aa1=bitmapHolder.getBitmapAndFree();

                          iv.setImageBitmap(aa1);

public Bitmap decodeSampledBitmapFromResource(byte[] aa)
    {
        return BitmapFactory.decodeByteArray(aa, 0, aa.length,option);
    }

I guess your package name contains an underscore but underscore is used to define package structure in JNI function definitions. 我想您的软件包名称包含一个下划线,但是下划线用于在JNI函数定义中定义软件包结构。 Probably "sounds_english" causes the problem. 可能是“ sounds_english”引起了问题。 I suggest you not to use underscores in your package structure. 我建议您不要在包结构中使用下划线。

The problem is the underscore in your package (like @user2359247 already mentioned). 问题是软件包中的下划线(例如已经提到的@ user2359247)。

Change all occurences of: 更改以下所有事件:

Java_com_example_sounds_english_JniBitmapHolder_jniStoreBitmapData
Java_com_example_sounds_english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData
Java_com_example_sounds_english_JniBitmapHolder_jniFreeBitmapData

to: 至:

Java_com_example_sounds_1english_JniBitmapHolder_jniStoreBitmapData
Java_com_example_sounds_1english_JniBitmapHolder_jniGetBitmapFromStoredBitmapData
Java_com_example_sounds_1english_JniBitmapHolder_jniFreeBitmapData

finally i got the solution: 终于我得到了解决方案:

I have changed my package name to soundsenglish 我已将包裹名称更改为soundsenglish

and changed my cpp code to 并将我的cpp代码更改为

Java_com_example_soundsenglish_JniBitmapHolder_jniStoreBitmapData Java_com_example_soundsenglish_JniBitmapHolder_jniGetBitmapFromStoredBitmapData Java_com_example_soundsenglish_JniBitmapHolder_jniFreeBitmapData Java_com_example_soundsenglish_JniBitmapHolder_jniStoreBitmapData Java_com_example_soundsenglish_JniBitmapHolder_jniGetBitmapFromStoredBitmapData Java_com_example_soundsenglish_JniBitmapHolder_jniFreeBitmapData

jni not support package with "_" jni不支持带有“ _”的软件包

package com.example.sounds_english

change to 改成

package com.example.sounds.english

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM