android应用System.loadLibrary卸载加载得库实例

android 加载库后,如果重复加载同一个库,会出现已经加载得警告,也就是说,就不会重新加载so文件。这时候需要kill掉对应得activity,然后重新启动activity就可以使得so重新加载,对应代码:

int pid = android.os.Process.myPid();

android.os.Process.killProcess(pid);

Android Jni 用动态库的加载与卸载函数说明

一、当 Android 的 Virtual Machine 执行到 System.loadLibrary( "动态库名" ) 函数时,

首先会去执行 C 语言动态库里的 JNI_OnLoad 函数。
它的用途有两个:
1)告诉 Virtual Machine 当前动态库使用了哪个版本的 Jni。
  如果当前动态库中没有提供 JNI_OnLoad 函数,
  Virtual Machine 会默认为动态库使用的是最老的 Jni 1.1 版本。
  由于新版 Jni 做了许多扩充,例如 Jni 1.4 的 java.nio.ByteBuffer。
2)动态库的开发者可以在 JNI_OnLoad 函数中进行动态库内的初始化设置(Initialization),
  将此动态库中提供的各个本地函数(Native Function)登记到 Virtual Machine 里,
  以便能加快以后调用动态库中的本地函数的效率,就是初始化设置的重要一项。
  应用层级的 Java 类通过 Virtual Machine 才能调用到动态库中的本地函数。
  如果没有注册登记过的话,Virtual Machine 就在 动态库名.so 里寻找要调用的本地函数。
  如果需要连续调用很多次且每次都需要寻找一遍的话,会多花许多时间。
  因此 C 语言动态库开发者可以自已将动态库中的本地函数向 Virtual Machine 进行注册登记。
代码示例:(注:由于新浪博客不支持 C 注释,所以请将 /* */ 想像替换为 /星 星/)
jint
JNI_OnLoad( JavaVM* vm,
            void*   reserved )
{
    jint    jintResult = -1;
    JNIEnv* env = NULL;
    /*Reference types, in C.
       typedef void*   jobject;
       typedef jobject jclass; */
    jclass  cls = NULL;

    /* typedef struct {
           const char* name;      /* Java 代码中调用的函数名字 */
           const char* signature; /* 描述了函数的 参数 和 返回值 */
           void*       fnPtr;     /* 函数指针转成无符号指针 */
       } JNINativeMethod;
       其中比较复杂的是第二个参数,
       例如 "()V" 或 "(II)V" 或 "(Ljava/lang/String;)V"
       实际上这些字符是与函数的 参数 及 返回值 类型是一一对应的,
       括号()中的字符表示参数,括号后面的则代表返回值,
       例如 "()V" 就表示 void 函数名();
          "(II)V" 就表示 void 函数名( int, int );
          "(Ljava/lang/String;)V" 就表示 void 函数名( jstring );
       具体的每一个字符所表示的意义下面部分有所详见 */
    /* 动态库中的本地函数信息数组 */
    JNINativeMethod aJNINativeMethod[] = {
        { "MeasureDistance",
          "(Ljava/lang/String;)V",
          (void*)Java_MyJni_MyNDK_MyDemo_MyJniNDKDemo_MeasureDistance }
    };
     /* #if defined(__cplusplus)
           typedef _JNIEnv JNIEnv;
           typedef _JavaVM JavaVM;
       #else
           typedef const struct JNINativeInterface* JNIEnv;
           typedef const struct JNIInvokeInterface* JavaVM;
       #endif */
    /* JavaVM::GetEnv 原型为 jint (*GetEnv)(JavaVM*, void**, jint); */
    /* GetEnv()函数返回的 Jni 环境对每个线程来说是不同的,*/
    /* 因此我们必须在每次进入函数时都要重新获取 */
    if ( JNI_OK != (*vm)->GetEnv( vm,
                                  (void**)env,
                                  JNI_VERSION_1_6 ) )
    {
        /* 输出的 log 一般是到 /dev/log/ 下的三个设备中,可以用 logcat 工具查看 */
        __android_log_write( ANDROID_LOG_INFO,               /* 日志信息 */
                             "MyJniDemo",                    /* 日志标签 */
                             "Call JavaVM::GetEnv failed" ); /* 日志内容 */
       return jintResult; /* 此时返回的是负壹(-1) */
    }
    /* 如果 将动态库中的本地函数向 Virtual Machine 进行注册登记失败 的话,则 */
    /* 由于 aJNINativeMethod 是一组 函数名称 与 函数指针 的对照表,
       在程序执行期间可以多次调用registerNativeMethods函数来更换注册登记本地函数 */
    /* #if defined(__cplusplus)
           typedef _JNIEnv JNIEnv;
           typedef _JavaVM JavaVM;
       #else
           typedef const struct JNINativeInterface* JNIEnv;
           typedef const struct JNIInvokeInterface* JavaVM;
       #endif */
    /* Reference types, in C.
       typedef void*   jobject;
       typedef jobject jclass; */
    /* struct JNINativeInterface 里的函数指针
       jint (*RegisterNatives)( JNIEnv*,
                                jclass,
                                const JNINativeMethod*,
                                jint ); */
    cls = (*env)->FindClass( env,
                             /* 下面的字符串就是描述 Java 代码中的主类 */
                             "MyJni/MyNDK/MyDemo/MyJniNDKDemo" );
    if ( 0 > (*env)->RegisterNatives( env,
                                      cls,
                                      aJNINativeMethod,
                                      sizeof( aJNINativeMethod ) /
                                      sizeof( aJNINativeMethod[0] ) ) )
    {
        /* 输出的 log 一般是到 /dev/log/ 下的三个设备中,可以用 logcat 工具查看 */
        __android_log_write( ANDROID_LOG_INFO,                   /*日志信息*/
                             "MyJniDemo",                        /*日志标签*/
                             "Register native methods failed" ); /*日志内容*/
       return jintResult; /* 此时返回的是负壹(-1) */
    }
   
    jintResult = JNI_VERSION_1_6;
    /* 此函数回传 JNI_VERSION_1_6 宏值给 Virtual Machine,
       于是 Virtual Machine 就知道当前动态库所使用的 Jni 版本了 */
    return jintResult; /* JNI_VERSION_1_6(0x00010006) */
}
 
二、JNI_OnUnload 函数与 JNI_OnLoad 函数相对应。

在 JNI_OnLoad 函数中进行的动态库内的初期化设置,
要在 Virtual Machine 释放该动态库时调用 JNI_OnUnload 函数来进行善后清除。
同 Virtual Machine 调用 JNI_OnLoad 一样,
调用 JNI_Unload 函数时,也会将 JavaVM 的指针做为第一个参数传递,原型如下:
jint
JNI_OnUnload( JavaVM* vm,
              void*   reserved );
              
三、JNINativeMethod::signature 描述字符串字符意义说明:

1)基本类型对应关系:

标识符  Jni 类型       C 类型
  V    void           void
  Z    jboolean       boolean
  I    jint           int
  J    jlong          long
  D    jdouble        double
  F    jfloat         float
  B    jbyte          byte
  C    jchar          char
  S    jshort         short
 
2)基本类型数组:(则以 [ 开始,用两个字符表示)

标识串  Jni 类型        C 类型
  [Z   jbooleanArray  boolean[]
  [I   jintArray      int[]
  [J   jlongArray     long[]
  [D   jdoubleArray   double[]
  [F   jfloatArray    float[]
  [B   jbyteArray     byte[]
  [C   jcharArray     char[]
  [S   jshortArray    short[]
 
3)类(class):(则以 L 开头,以 ; 结尾,中间是用 / 隔开的 包 及 类名)

标识串        Java 类型  Jni 类型
L包1/包n/类名;     类名     jobject
例子:
Ljava/net/Socket; Socket      jobject

4)例外(String 类):

标识串               Java 类型  Jni 类型
Ljava/lang/String;  String    jstring

5)嵌套类(类位于另一个类之中,则用$作为类名间的分隔符)

标识串                         Java 类型  Jni 类型
L包1/包n/类名$嵌套类名;              类名      jobject
例子:
Landroid/os/FileUtils$FileStatus;  FileStatus  jobject

时间: 2024-07-30 01:08:06

android应用System.loadLibrary卸载加载得库实例的相关文章

Android开发实现自定义新闻加载页面功能实例

本文实例讲述了Android开发实现自定义新闻加载页面功能.分享给大家供大家参考,具体如下: 一.概述: 1.效果演示: 2.说明:在新闻页面刚加载的时候,一般会出现五种状态 未知状态(STATE_UNKNOW).空状态(STATE_EMPTY).加载中(STATE_LOADING).错误(STATE_ERROT).成功(STATE_SUCCESS) 因为每个Detail页面都会出现,所以我们可以把他们封装成一个LoadPage的自定义view,可以复用 二.实现: 1.首先的定义三个布局,为什

android 源码中使用System.loadLibrary加载第三方库

问题描述 android 源码中使用System.loadLibrary加载第三方库 我在android源码中编译一个apk,使用了几个第三方库文件,下面是Android.mk文件内容: LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := debug optional eng LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_PACKAGE

Android开发中如何解决加载大图片时内存溢出的问题

Android开发中如何解决加载大图片时内存溢出的问题    在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给大家.   尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存. 因此,改用先通过Bitmap

Android实现简单的分批加载ListView_Android

每次滑动至底端,从数据库中获取10条数据,并加载于ListView中 数据库 package com.example.listviewbatchloading; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlit

Android 开发中fragment预加载问题

我们在做应用开发的时候,一个Activity里面可能会以viewpager(或其他容器)与多个Fragment来组合使用,而如果每个fragment都需要去加载数据,或从本地加载,或从网络加载,那么在这个activity刚创建的时候就变成需要初始化大量资源.这样的结果,我们当然不会满意.那么,能不能做到当切换到这个fragment的时候,它才去初始化呢? 答案就在Fragment里的setUserVisibleHint这个方法里.请看关于Fragment里这个方法的API文档(国内镜像地址:ht

Android实现简单的分批加载ListView

每次滑动至底端,从数据库中获取10条数据,并加载于ListView中 数据库 package com.example.listviewbatchloading; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlit

android Html内容如何预先加载到缓存,提高webview刷新速度呢

问题描述 android Html内容如何预先加载到缓存,提高webview刷新速度呢 因为在webview加载html内容的时候,需要解析html内容,再加载到webview里面,导致显示速度比较慢,如何在得到html内容的前提下,预先加载到缓存,提高webview的显示速度呢? 解决方案 浏览器的作用就是将得到的数据显示出来,跟你得到文本流再在textview中显示一样,你说的渲染太耗时除非是你过去网络资源时没有开辟子线程,或者要显示的图形或者js太复杂.另外webview相当于你使用了一个

android-当旋转Android屏幕时App自动加载数据

问题描述 当旋转Android屏幕时App自动加载数据 我打开我的应用时数据会自动加载,我的问题是:当屏幕是垂直的时候应用会从服务器上加载下数据,但当屏幕旋转的时候,它又重新加载数据,在垂直状态又重新加载,旋转也是,一直如此.我应该怎么做才能让它不重新加载数据,希望大家能帮我看看,应该如何处理. 程序代码如下: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setCont

界面-Android中Fragment怎样重新加载UI

问题描述 Android中Fragment怎样重新加载UI 有这么一个需求:我从AFragment跳转到了一个Activity,在这个Activity中我做了一些操作(这些操作会让AFragment中使用的数据发生变化,从而选择不同的视图UI),然后点击回退按钮时,我希望AFragment中的界面能够根据Activity中的操作而变化.大神们,帮忙看看! 解决方案 考虑下用事件总线,有两个比较好的库EventBus和Otto 解决方案二: 感觉楼上的方法比较合理,但也可以用比较粗暴的广播的方法