修改Jar内容

例子

最近线上报了一个java.lang.UnsatisfiedLinkError的错误,发现环信内部没有将某个loadLibrary方法try catch(error),但是其内部的_loadLibrary方法是try catch(error)的,所以准备做以下修改:
hyphenatechat_3.4.2.jar中的EMClient.class文件中的loadLibrary方法做以下替换:

private static void loadLibrary() {
    if (!libraryLoaded) {
        _loadLibrary("sqlite");
        _loadLibrary("hyphenate_av");
        _loadLibrary("hyphenate_av_recorder");
        System.loadLibrary("hyphenate");
        libraryLoaded = true;
    }

}

替换为

private static void loadLibrary() {
    if (!libraryLoaded) {
        _loadLibrary("sqlite");
        _loadLibrary("hyphenate_av");
        _loadLibrary("hyphenate_av_recorder");
        _loadLibrary("hyphenate");
        libraryLoaded = true;
    }

}

环境

Windows

需要下载内容

使用步骤

  1. 依赖javassist Jar;
  2. 使用jar xvf oldJar.jar命令解压缩oldJar到当前目录下;
  3. 编写代码;
  4. 使用jd-gui验证newClass文件是否正确;
  5. 使用jar cvfm META-INF\MANIFEST.MF newJar.jar *命令将当前目录下的所有文件压缩成newJar,并且使用环信生成的MANIFEST.MF;
  6. 用newJar替换工程中的Jar。

3.代码

package com.fqxyi.androidutils.test;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

/**
 * Java方法测试类
 */
public class JavaTest {

    public static void main(String[] args) {
        try {
            modifyClass();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void modifyClass() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        //设置目标类的路径
        pool.insertClassPath("C:\\Users\\Administrator\\Desktop\\hyphenatechat_3.4.2\\") ;
        //获得要修改的类
        CtClass cc =pool.get("com.hyphenate.chat.EMClient");//就是对EMClient.class的映射
        //得到方法
        CtMethod m = cc.getDeclaredMethod("loadLibrary");
        //可以在函数的开头插入新的代码
        //m.insertBefore("{return true;}") ;
        //也可以自定义loadLibrary方法的内容
        m.setBody("{if (!libraryLoaded)\n" +
                "    {\n" +
                "      _loadLibrary(\"sqlite\");\n" +
                "      _loadLibrary(\"hyphenate_av\");\n" +
                "      _loadLibrary(\"hyphenate_av_recorder\");\n" +
                "      _loadLibrary(\"hyphenate\");\n" +
                "      libraryLoaded = true;\n" +
                "    }}");
        //保存到文件里,会在项目根目录下生成一个EMClient.class,并没有自动替换EMClient.class,需要自己手动替换进去
        cc.writeFile() ;
    }

}

参考文章

更好的方式

AOP:以后总结

添加新评论