多个ClassLoader加载同一个so动态库失败

为解决热更新中SO库加载冲突,本文探讨了一种有效策略:将SO包置于DEX文件内,避免重复加载。在更新前不加载SO包至内存,随DEX包更新下载,删除旧SO包,加载新SO包,实现单次加载。

有时候我们需要做热更新,所以如果更新包里面有so库的话。可能需要重新加载。但是更新前的classLoader已经加载过该动态库了,Java VM 为了确保ClassLoader的命名空间独立性。不允许两个ClassLoader加载同一个动态库。那么只要把更新下来的so文件命名成一个新的名字,并且使用两个不同的没有继承关系的CLassLoader加载就行了。

    你以为这样就可以了吗?不是的。这种方法在多数机型里面测试可以使用,但是在华为手机里面就直接卡住了。具体原因不清楚。所以最好的办法是,把so包放在dex文件里面。没更新之前先不加载so包到内存。而是随着dex包一下更新下载下来。然后删除掉旧的so包,使用新的so包。然后再把so包加载到内存里面。这样,整个过程就加载一次so包。

 

 

简要介绍: 本工具是对java class文件进行加密保护的工具!本工具全面支持linux/unix/windows操作系统。 众所周知,java编译后的class文件是一种中间字节字文件, 很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式, 但这样会带来很麻烦,而且也不能真正保护class文件, 本工具是对class文件进行加密,采用jni的方式解密运行, 加密算法达到256位,加密后的class文件不可能被破解,反编译工具也对加密后的class文件无能为力。 运行方式: 运行时,要能正确的加载加密后的class文件, 必须使用我们提供的动态链接库classloader.dll(wndows操作系统)或者libclassloader.so(Linux、Unix操作系统)。 执行java时带上参数-agentlib:\classloader 注意此处不要后缀名.dll(或者.so)。 如: windows下执行java: java -agentlib:C:\classloader HelloWorld Linux、Unix等系列操作系统下执行java: java -agentlib:/home/classloader HelloWorld 应用场合: 独立的应用程序,运行java时,带上参数-agentlib:\classloader Tomcat、Jboss等Java application server修改启动脚本, 把执行java的命令行后面加上参数-agentlib:\classloader 适应环境: 操作系统:所有操作系统,Windows系统、Linux/Unix,只是运行时, 使用的动态链接库文件不一样而已,其它配置完全一样。 jdk必须1.5以上。 下载地址: http://www.cr8ge.com/admin/upload/2011020917102317195.rar http://www.kmcxzs.cn/admin/upload/2011020917131925480.rar
从错误日志来看,**崩溃确实发生在 `libart.so`(Android Runtime 的核心库)中**,但 **根本原因可能并非 `libart.so` 自身的问题**,而是由 **应用层或系统环境触发的异常** 导致 ART 执行失败。以下是详细分析: --- ### **1. `libart.so` 的角色** - **ART(Android Runtime)** 是 Android 的虚拟机,负责执行 Java/Kotlin 字节码、管理内存和线程等。 - `libart.so` 是 ART 的核心动态库,当应用出现 **未处理的异常、内存错误或 JNI 调用违规** 时,ART 可能会在内部抛出 SIGSEGV。 --- ### **2. 为什么崩溃会出现在 `libart.so`?** #### **(1) 应用层代码触发了 ART 的保护机制** - **Java 代码的未捕获异常**(如 `NullPointerException`)可能被 ART 转换为底层信号(SIGSEGV)。 - **JNI 调用违规**(如错误使用 `jobject` 引用)导致 ART 的引用管理失败。 #### **(2) 系统环境问题** - **内存不足**:ART 无法分配所需内存(如加载 Dex 或类时)。 - **HarmonyOS 兼容性差异**:某些 ART 行为可能与标准 Android 不同。 #### **(3) 日志中的关键线索** - 你的日志显示崩溃发生在 **应用初始化阶段**(`LoadedApk.makeApplication`),说明可能是: - 应用主类(`Application` 子类)的构造函数或 `onCreate()` 抛出了异常。 - 动态加载的 Dex 或资源(如 `assets`)损坏。 --- ### **3. 如何判断是否是 `libart.so` 的自身缺陷?** - **复现范围**: - 如果 **仅此应用崩溃**,其他应用正常 → 问题在应用层。 - 如果 **多个应用随机崩溃** → 可能是系统或 ART 缺陷(需检查系统新)。 - **崩溃堆栈**: - 若堆栈指向 ART 内部函数(如 `art::ClassLinker::LoadClass`),可能是 **类加载失败**(应用 Dex 问题)。 - 若指向 `art::JavaVMExt::JNI` → **JNI 调用错误**(如 Native 代码传入了无效参数)。 --- ### **4. 解决方案** #### **(1) 应用层修复** - **检查 Java 代码**:确保主类(`Application`)和无参构造函数无异常。 - **验证 JNI 代码**: ```c // 示例:正确管理 GlobalRef jobject globalRef = env->NewGlobalRef(obj); // ...使用后必须释放 env->DeleteGlobalRef(globalRef); ``` - **测试纯净环境**:清除应用数据或卸载重装。 #### **(2) 系统/ART 层面** - **新系统**:修复可能的 ART 缺陷(尤其是 HarmonyOS 的补丁版本)。 - **降级应用目标 SDK**:某些 ART 版本对高 SDK 兼容性较差。 #### **(3) 调试工具** - **AddressSanitizer (ASan)**:检测 Native 内存错误。 - **ART 日志**:启用详细日志定位类加载问题: ```bash adb shell setprop dalvik.vm.extra-opts "-Xlog:verifier,classloader" adb logcat | grep art ``` --- ### **5. 典型场景示例** - **案例 1**:应用在 `onCreate()` 中访问了未初始化的静态变量 → ART 转换为 SIGSEGV。 - **案例 2**:JNI 层未正确处理 `jstring` 转换 → ART 引用表溢出。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昆仑双开分身

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值