用 javassist 来修改 class 文件
2013-03-07 00:28
190 查看
在一个老项目中,不知是哪位牛人写的程序,调用了FileInputStream,但是没有关闭文件流。而这个地方是最常用的一个地方,导致系统运行一段时间之后内存耗尽,报文件句柄数过多的错误。
处理这种问题,如果有源码,加上关闭文件流的操作即可。但是,由于公司的源码管理得不好,这个项目的源码已经丢失了,没有源码,只能反编译得到源码加上关闭文件流的操作再编译一次,这样编译出来的class文件跟原来的class文件里面的一些变量有差异,替换之后会引起另外一个更严重的问题:链接走正常路线的时候可以访问,但是走通过F5负载均衡的时候就不能访问了。
这个问题相当的棘手,因为以替换class文件,就会引起更严重的问题,但是文件句柄不释放的问题也很重要。至于"通过F5负载均衡的时候为什么不能访问"这个问题,由于对F5负载均衡不了解,通过解决这个问题来解决句柄问题看起来很不可能。于是想到了用开源的jar包来直接修改class文件,直接在class文件中直接添加将文件流关闭的操作。
在网上查资料之后有两种方式来编辑class文件:classEdit和javassist。我用了javassist来修改class文件,在class文件中添加关闭文件流的操作之后,重新生成了一个class文件,用这个class文件和修改前的class文件反编译对比,非常的完美,就只比修改前的文件多了关闭文件流的操作,其他的地方一模一样。
修改calss文件的示例代码如下:
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class Test {
public static void main(String[] args) throws Exception {
ClassPool classPool = ClassPool.getDefault();
// 必须将class文件放在这个工程编译后的class文件中,路径也对应起来
CtClass ctClass = classPool.get("com.ambitionstone.esa2000.pki.AZTPkiServlet");
//设置方法需要的参数,一定要能匹配起来,而且必须引入这些参数类的包
CtClass[] param = new CtClass[4] ;
param[0] = classPool.get("javax.servlet.http.HttpServletRequest") ;
param[1] = classPool.get("javax.servlet.http.HttpServletResponse") ;
param[2] = classPool.get("int") ;
param[3] = classPool.get("java.lang.String") ;
// 找到需要修改的行所在的方法
CtMethod method = ctClass.getDeclaredMethod("doOnlineValidate", param);
// 在这个方法的182行添加关闭文件流的方法
method.insertAt(182, "fin.close();");
// 将文件写到指定的目录,生成之后在test\com\ambitionstone\esa2000\pki\AZTPkiServlet\这个文件夹下面可以找到编译后的类
ctClass.writeFile("D:\\test") ;
}
}
javassist.jar 是一个比较常见的包,网上一搜就能搜到,这里就不在添加了。
来自为知笔记(Wiz)[Attachments]
处理这种问题,如果有源码,加上关闭文件流的操作即可。但是,由于公司的源码管理得不好,这个项目的源码已经丢失了,没有源码,只能反编译得到源码加上关闭文件流的操作再编译一次,这样编译出来的class文件跟原来的class文件里面的一些变量有差异,替换之后会引起另外一个更严重的问题:链接走正常路线的时候可以访问,但是走通过F5负载均衡的时候就不能访问了。
这个问题相当的棘手,因为以替换class文件,就会引起更严重的问题,但是文件句柄不释放的问题也很重要。至于"通过F5负载均衡的时候为什么不能访问"这个问题,由于对F5负载均衡不了解,通过解决这个问题来解决句柄问题看起来很不可能。于是想到了用开源的jar包来直接修改class文件,直接在class文件中直接添加将文件流关闭的操作。
在网上查资料之后有两种方式来编辑class文件:classEdit和javassist。我用了javassist来修改class文件,在class文件中添加关闭文件流的操作之后,重新生成了一个class文件,用这个class文件和修改前的class文件反编译对比,非常的完美,就只比修改前的文件多了关闭文件流的操作,其他的地方一模一样。
修改calss文件的示例代码如下:
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class Test {
public static void main(String[] args) throws Exception {
ClassPool classPool = ClassPool.getDefault();
// 必须将class文件放在这个工程编译后的class文件中,路径也对应起来
CtClass ctClass = classPool.get("com.ambitionstone.esa2000.pki.AZTPkiServlet");
//设置方法需要的参数,一定要能匹配起来,而且必须引入这些参数类的包
CtClass[] param = new CtClass[4] ;
param[0] = classPool.get("javax.servlet.http.HttpServletRequest") ;
param[1] = classPool.get("javax.servlet.http.HttpServletResponse") ;
param[2] = classPool.get("int") ;
param[3] = classPool.get("java.lang.String") ;
// 找到需要修改的行所在的方法
CtMethod method = ctClass.getDeclaredMethod("doOnlineValidate", param);
// 在这个方法的182行添加关闭文件流的方法
method.insertAt(182, "fin.close();");
// 将文件写到指定的目录,生成之后在test\com\ambitionstone\esa2000\pki\AZTPkiServlet\这个文件夹下面可以找到编译后的类
ctClass.writeFile("D:\\test") ;
}
}
javassist.jar 是一个比较常见的包,网上一搜就能搜到,这里就不在添加了。
来自为知笔记(Wiz)[Attachments]
相关文章推荐
- Myeclipse中的使用javassist修改时class文件时生成的class文件在项目的根目录下。
- 使用Javassist对.class文件进行修改
- 使用Javassist对.class文件进行修改
- 用 javassist 来修改 class 文件
- 使用javassist修改class文件
- 使用Javassist对.class文件进行修改(AOP面向切面编程)
- java反编译软件jd-gui.exe以及使用javassist修改class文件 .
- 直接修改别人jar包里面的class文件 工具:jclasslib
- 如何实现SVN导出某段时间修改过的文件;自动将class文件部署到服务器中;重启服务器
- Classworking 工具箱: 注释(Annotation)与 ASM 自动化运行时类文件修改
- 直接修改class文件内容即使是文本会导致App异常,正确方式是修改java再用生成的class替换掉原有的class
- Java代码加密与反编译(二):用加密算法DES修改classLoader实现对.class文件加密
- 直接修改别人jar包里面的class文件 工具:jclasslib
- javassis在spring初始化前修改class文件。
- 破解 jar 包之直接修改 .class 文件方式
- 直接修改别人jar包里面的class文件 工具:jclasslib
- 【修改jar】jclasslib修改jar包里面的class文件
- 通过自定义Gradle插件修改编译后的class文件
- 查看与修改字节码,从而实现替换他人jar包中class文件的目的
- .class 字节码文件修改