【问题标题】:Making an Android Studio JNI static lib to be read by JNI让 JNI 读取 Android Studio JNI 静态库
【发布时间】:2015-11-30 08:15:57
【问题描述】:

硬件手机和平板电脑的内存太少,但 HAXM 工作正常?

我的基本问题是我的应用程序(很可能是我的 Java 应用程序加载的 JNI 动态库)太大。 Java 应用程序在未使用硬件电话和模板调用 JNI 指令的情况下崩溃。但是,它可以与仅扩大自身主内存的 HAXM 仿真器一起正常工作。

我认为我需要减小 JNI 动态库的大小。

我有大量的 C 函数,其中大部分没有使用?

涵盖应用程序编程的一个主题领域,超过 64000 个条目和 995 个被使用。在 Win32 中创建一个 C 程序链接器过滤掉未使用的东西。真流畅。

然而,在 Android Studio 中,我像往常一样拥有一个使用动态 JNI 库编写的 Java 应用程序,即 Android JNI 标准使用。没有链接器确定使用或不使用哪些功能。但是,我有一个调用其他 C 函数的前端 JNI 文件。 Java 系统不会分析调用了哪些 JNI 函数并找到能够对其进行排序的调用树,我假设? (我认为,WIN32 中的 DLL 也不会这样做,因为它不知道会调用什么。)

静态库方法可能有效,我该怎么做?

一个想法是创建一个包含大量 C 函数的静态库,当标准 Android JNI 通过从前端 JNI 文件调用来使用它时,我假设这只会使用所需的静态库的函数并删除其余部分,例如链接 Win32 C 程序时。我可能错了?

好吧,我试图了解如何在 Android Studio 中创建静态库,以及如何使用专有静态库链接到 JNI 动态库。然而,通过谷歌搜索或通过 stackoverflow 搜索很难找到。我认为这种方法很少见。

  • 有谁知道如何在 Android Studio 中制作静态 JNI 库
  • 有谁知道如何在 Android Studio 中使用静态 JNI 库制作带有 JNI 前端调用静态库函数?
  • 并且能够描述它吗?
  • 这在 JNI 中可能是不可能的,然后很高兴知道它是 不可能的。是否有可能以这种方式进行这种优化?

【问题讨论】:

  • 您是否尝试将默认符号可见性设置为hidden 并垃圾收集未使用的代码/数据部分?见blog.algolia.com/android-ndk-how-to-reduce-libs-size
  • 这个问题没有显示任何研究工作 -1 在我看来是不公平的。看,几个月前Android studio NDK的整个环境都换了1.3版本,连个android.mk文件都看不到了,只有一个build.gradle。 Android Studio 指南并没有真正完全更新,NDK 页面也根本没有。即使没有,将 NDK 作为单独的安装运行,静态库问题在 stckoverflow 中也非常罕见。关于android/gradle链接器优化的信息,告诉我在哪里可以找到?
  • 如果你想在使用 Gradle 构建时使用你自己的 Android.mk,关于如何做到这一点已经存在几个问题。例如。 stackoverflow.com/questions/32970094/…
  • @Michael,现在我们正在讨论正确的主题,以及深入调查和测试的好线索。如果它们刚刚打开,似乎有内置优化(为什么默认情况下它们不是一个谜。他们仍在处理 android.mk 和 ap.mk 脚本,但可能可以转换为 AS1.3+ gradle。让我们看看结果如何?
  • 是的@Michael,在 app build gradle 中有一个有趣的部分: android.ndk { moduleName = "AndroidRosetta" /* * 此处可配置的其他 ndk 标志是 * cppFlags += "-fno-rtti " * cppFlags += "-fno-exceptions" * ldLibs = ["android", "log"] * stl = "system" */ } 想知道它的文档在哪里。我会搜索一下。 (看起来可能设置了许多链接器/编译器标志。正是我想要的。)

标签: android c++ c android-ndk


【解决方案1】:

您可以在 Android Studio 中使用静态库,但您应该使用 Android.mk 作为配置,使用 ndk-build 构建它。

在您的 build.gradle 中,您可以参考这个预建库“c:\android\obj\libmystatic.a”:

model {
    android.ndk {
        moduleName = "hello-jni"
        abiFilters += armeabi-v7a
        ldFlags += "-LC:/android/obj"
        ldLibs += "mystatic"
    }
}

【讨论】:

    【解决方案2】:

    问题是如何忽略 JNI 文件中未使用的函数

    我在@Michaels 提示的帮助下回答了我自己的问题。

    基本问题是 HW Samsung Tab3 的 APK 太大,所以它会崩溃,而 HAXM 工作正常。我最初使用一个小的 JNI 假人在 Tab3 中制作了作品,但不是真正的 JNI 代码。我的假设是它太大了,是吗?

    如果可以通过其他方式进行优化,那么在制作动态自动 JNI 库时使用它来制作静态库的想法是多余的。令人恐惧的是手动整理超过 64K 条目中使用的内容。无论如何感谢@Alex。

    是的,可以通过在应用程序 gradle 中设置以下标志来进行优化:

    android.ndk {
        moduleName = "XXXX"
        cppFlags.add("-ffunction-sections")
        cppFlags.add("-fdata-sections")
        cppFlags.add("-fvisibility=hidden")
        CFlags.add("-ffunction-sections")
        CFlags.add("-fdata-sections")
        CFlags.add("-fvisibility=hidden")
        ldFlags.add("-Wl,--gc-sections")
        /*
         * Other ndk flags configurable here are
         * cppFlags += "-fno-rtti"
         * cppFlags += "-fno-exceptions"
         * ldLibs    = ["android", "log"]
         * stl       = "system"
         */
    }
    

    这将我的 APK 从 11Mb 减少到 7Mb(删除了 JNI 部分中未使用的函数)。并且在应用程序中进行了一些更改,将 Win64 应用程序从 0,9Mb 减少到 0,6Mb,将 APK 减少到 6Mb。将 Build 变体设置为 arm7 调试(Tab3),APK 为 2.7MB,但仍然崩溃(在 Main java 中的 load jni library 命令上)。

    我如何知道发布大小? - 可以测试吗?

    问题是 APK 在发布模式下会有多大(我假设它小于调试模式),但必须对发布版本进行签名等,我的意图不是向市场发布应用程序,而是测试它的大小,看看计划中的应用程序是否可能适合商业 Android 硬件单元。如果不是,我必须对我计划的应用程序进行总体重新设计,但是要明智得多。但是重新设计是一项巨大的工作,我宁愿确定最初的计划是不可能的?看到像 MS Office 副本这样的应用程序,我认为这一定是可能的。

    试图摆弄构建/编辑风格,Gradle 只是抱怨放弃了调试功能,所以这是一条死胡同。

    所以现在的问题是:

    有没有可能在不商业发布的情况下找出并尝试发布形式的应用程序?

    【讨论】:

    • 新问题应该作为问题发布,而不是作为答案发布。
    • 我发现我的应用程序在 ARM7 硬件单元中崩溃而不是在 HAXM 中崩溃的原因是错误的(不是内存问题)。这是由于 stdlib atof 的问题(将其更改为 strtod 并加载)导致崩溃加载 JNI 库。请参阅:code.google.com/p/android/issues/detail?id=73725)。我现在对 ARM7 JNI 有一些其他不同的问题。但是我仍然对“有没有可能在不商业发布的情况下找出并尝试发布形式的应用程序?”这个问题感兴趣?
    • ..这是一个新问题,因此应该这样发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2018-04-05
    • 2017-05-17
    相关资源
    最近更新 更多