哪位高手动了他的jar包(三)
谁动了他的jar包(三)
接
谁动了他的jar包(一) http://ilab.iteye.com/blog/984823
谁动了他的jar包(二) http://ilab.iteye.com/blog/1002629
一的方法侵入性较强,可维护性较差.
二的方法逻辑分工明确,维护性较好,使用起来简单.但无法适用所有的修改情况;
对于不同情况的类,要进行不同的反射改造,和继承.
特别的,对于,final标识的属性或者类来说,二的方法,就无能为力了.
有没有两全其美的方法呢,既可以做到无侵入,易维护,并且可以适用于所有不同的情况,达到完美的替换,以达到修改jar包的目的呢;
可以试试,用jvmti~.
先简单介绍下
http://download.oracle.com/javase/1.5.0/docs/guide/jvmti/
偷个懒,直接翻译了![哪位高手动了他的jar包(三) 哪位高手动了他的jar包(三)](/default/index/img?u=aHR0cDovL3d3dy5teWV4Y2VwdGlvbnMubmV0L2ltZy8yMDEyLzEwLzE5LzE0NDEzNDM0MjIuZ2lm)
jvm 工具接口(jvmti) 是一种新的本地编程工具接口.
通过它,你可以对虚拟机中的程序进行监控,也能够控制其执行;
jvmti 支持了所有的需要访问虚拟机状态的工具,
包括,但不仅限于: 分析,调试(debug),监控,线程分析,覆盖分析工具;
jvmti 用来替代 jvmpi及jvmdi(原来的分析调试工具);
"控制其执行",是否包括,改变某些类的执行方式呢.答案是肯定的,我们现在仍然用上面的例子,
来演示下如何用jvmti的技术,来达到我们的目的;
新建类Transformer,实现 java.lang.instrument.ClassFileTransformer
以及类Premain
打成jar包premain.jar,修改\META-INF\MANIFEST.MF
为
这样,我们就简单完成了一个类代理的小工具;
该工具的作用是,监控jvm所有加载的类,当该类是在transferClass中配置有存在时,从D盘读取.class文件进行替换;
我们来试下功能:)
修改Feature
将.class文件放在D:盘根目录 ,将premain.jar包也放在根目录
此时再将Feature改回来
执行
输出, 为 null
嗯是的,因为没加参数
设置runConfigration VMargument 为 -javaagent:D:/premain.jar
然后,再跑下?
输出,
![哪位高手动了他的jar包(三) 哪位高手动了他的jar包(三)](/default/index/img?u=aHR0cDovL3d3dy5teWV4Y2VwdGlvbnMubmV0L2ltZy8yMDEyLzEwLzE5LzE0NDEzNDM0MjIuZ2lm)
请参看 http://ilab.iteye.com/blog/984823 的第一段
以及 http://ilab.iteye.com/blog/1002629 的二楼评论![哪位高手动了他的jar包(三) 哪位高手动了他的jar包(三)](/default/index/img?u=L2ltYWdlcy9zbWlsZXMvaWNvbl9zbWlsZS5naWY=)
:)
接
谁动了他的jar包(一) http://ilab.iteye.com/blog/984823
谁动了他的jar包(二) http://ilab.iteye.com/blog/1002629
一的方法侵入性较强,可维护性较差.
二的方法逻辑分工明确,维护性较好,使用起来简单.但无法适用所有的修改情况;
对于不同情况的类,要进行不同的反射改造,和继承.
特别的,对于,final标识的属性或者类来说,二的方法,就无能为力了.
有没有两全其美的方法呢,既可以做到无侵入,易维护,并且可以适用于所有不同的情况,达到完美的替换,以达到修改jar包的目的呢;
可以试试,用jvmti~.
先简单介绍下
http://download.oracle.com/javase/1.5.0/docs/guide/jvmti/
偷个懒,直接翻译了
jvm 工具接口(jvmti) 是一种新的本地编程工具接口.
通过它,你可以对虚拟机中的程序进行监控,也能够控制其执行;
jvmti 支持了所有的需要访问虚拟机状态的工具,
包括,但不仅限于: 分析,调试(debug),监控,线程分析,覆盖分析工具;
jvmti 用来替代 jvmpi及jvmdi(原来的分析调试工具);
"控制其执行",是否包括,改变某些类的执行方式呢.答案是肯定的,我们现在仍然用上面的例子,
来演示下如何用jvmti的技术,来达到我们的目的;
新建类Transformer,实现 java.lang.instrument.ClassFileTransformer
public class Transformer implements ClassFileTransformer { public static Properties transferClass = new Properties(); static { transferClass.put("Feature", "Feature.class"); } // 获取我们指定的想要的类的原代码,这里的代码很偷懒...具体怎么获取可以根据场景而定 public static byte[] getBytesFromFile(String target) { try { System.out.println("start replacing"); InputStream is = new FileInputStream(new File("D:/" + target)); // bytes空间大于目标类即可,这里只做简单演示;完整的处理,可能需要做循环读取数据到bytes; byte[] bytes = new byte[1024 * 1024]; int length = is.read(bytes); byte[] rs = new byte[length]; System.arraycopy(bytes, 0, rs, 0, length); is.close(); return rs; } catch (Exception e) { System.out.println("error occurs in _ClassTransformer!" + e.getClass().getName()); e.printStackTrace(); return null; } } public byte[] transform(ClassLoader l, String className, Class<?> c, ProtectionDomain pd, byte[] b) throws IllegalClassFormatException { String temp = transferClass.getProperty(className); if (temp != null && temp.length() > 0) { System.out.println("stealing : " + className); return Transformer.getBytesFromFile(temp); } return null; } }
以及类Premain
public class Premain { public static void premain(String agentArgs, Instrumentation inst) throws ClassNotFoundException, UnmodifiableClassException { inst.addTransformer(new Transformer()); } }
打成jar包premain.jar,修改\META-INF\MANIFEST.MF
为
Manifest-Version: 1.0 Class-Path: . Premain-Class: Premain
这样,我们就简单完成了一个类代理的小工具;
该工具的作用是,监控jvm所有加载的类,当该类是在transferClass中配置有存在时,从D盘读取.class文件进行替换;
我们来试下功能:)
修改Feature
public class Feature { private String content; public Feature(){ this.content = "hello kitty"; } public void show() { System.out.println(this.content); } }
将.class文件放在D:盘根目录 ,将premain.jar包也放在根目录
此时再将Feature改回来
public class Feature { private String content; public void show() { System.out.println(this.content); } }
执行
public class Test { public static void main(String[] args) throws Exception { Function function = new Function(); function.show(); } }
输出, 为 null
嗯是的,因为没加参数
设置runConfigration VMargument 为 -javaagent:D:/premain.jar
然后,再跑下?
输出,
stealing : Feature start replacing hello kitty
1 楼
hastune
2011-04-19
谢谢博主分享,不知道能不能说说具体的场景。
及一般要用到替换jar包的情况。
及一般要用到替换jar包的情况。
2 楼
yfyh87
2011-04-20
hastune 写道
谢谢博主分享,不知道能不能说说具体的场景。
及一般要用到替换jar包的情况。
及一般要用到替换jar包的情况。
请参看 http://ilab.iteye.com/blog/984823 的第一段
以及 http://ilab.iteye.com/blog/1002629 的二楼评论
3 楼
zmty123
2011-05-10
设置runConfigration VMargument 为 -javaagent:D:/premain.jar
这个在哪设置呢!
这个在哪设置呢!
4 楼
littleJava
2011-05-18
受益不少,多谢!
5 楼
yfyh87
2011-05-19
littleJava 写道
受益不少,多谢!
:)