序
例子
最近线上报了一个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
需要下载内容
使用步骤
- 依赖javassist Jar;
- 使用
jar xvf oldJar.jar
命令解压缩oldJar到当前目录下; - 编写代码;
- 使用
jd-gui
验证newClass文件是否正确; - 使用
jar cvfm META-INF\MANIFEST.MF newJar.jar *
命令将当前目录下的所有文件压缩成newJar,并且使用环信生成的MANIFEST.MF; - 用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:以后总结