哈,你想改变jar包某个类的运行方式?
或是因为业务需要,或是因为这个jar暂时不能满足你你欲望...
或者只是for Fun!
但是你无法改变这个jar包,可能因为是公用的,可能因为产品的生成依赖于标准仓库,或者仅仅是你不想用 "编译一下你的java类,然后把你的.class替换进去" 这么...这么..这么...的方法,那你要怎么做?
例如:
有类 Feature
public class Feature {
private String content;
public void show() {
System.out.println(this.content);
}
}
及类 Function
public class Function {
private Feature f;
public void show() {
this.f.show();
}
}
测试类 Test,运行结果为 null . 而你想让他输出hello kitty
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
Function function = new Function();
function.show();
}
}
最先想到的方法是就是直接建一个同包同名类,在你的eclipse或者其它编译环境下;然后把相关方法,改成自己想要的方法;如下:
public class Feature {
private String content;
public Feature(){
this.content = "hello kitty";
}
public void show() {
System.out.println(this.content);
}
}
然后,你会发现,使用的是你的class吖,而不是jar包里的吖.
但是,如果你的程序也打成jar包,和原jar一起运跑,会是什么情况呢;
你可能发现,会输出 空,如果运气好,也可能 输出 hello kitty ;
为啥呢? 因为当有同包同名类时,classLoader总会尝试先加载到一个,而且加载到这个class文件后,后面就不会再加载;这个先加载到的类一般和classpath设置的先后有关;
在eclipse环境下,会先加载编辑器下的类,然后优先加载,先导入的类库;
如果先加载到你的类,那么就会输出 "hellokitty".
假如需要在生产环境指定加载你的类,
而且,
你无法预知客户如何设置classPath的先后顺序,那么,要怎么办呢?
可否自己写一个classLoader只加载目标类,而让你的调用程序在此classLoader环境下运行?
Let us try try : 先写出这个特别的classLoader
public class HoneyLoader extends URLClassLoader {
public HoneyLoader(URL[] urls, ClassLoader parent){
super(urls, parent);
}
public synchronized Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> c = findLoadedClass(name);
if (c != null) {
return c;
}
//先自己在指定位置(通过urls指定)找,找不到交给父类
try {
c = this.findClass(name);
} catch (Exception e) {
c = super.loadClass(name);
}
return c;
}
}
回到我们的测试类,修改如下
public class Test {
public static void main(String[] args) throws Exception {
// 根据jar包名称,获取我们需要的jar包的名称的url
String jarName = "feature2.jar";
URL url = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> urls = loader.getResources("Feature.class");
int i = 0;
while (urls.hasMoreElements()) {
url = urls.nextElement();
i = url.getPath().indexOf(jarName);
if (i > -1) {
break;
}
}
// 用honeyLoader启动我们的运行环境
ClassLoader myLoader = new HoneyLoader(new URL[] { new URL(url.getPath().substring(0, i) + jarName) }, loader);
Object object = myLoader.loadClass("Feature").newInstance();
object.getClass().getMethod("show").invoke(object);
}
运行结果:
hello kitty
呵呵~ 成功了
---------------------------------------------------------
你能想到其它更简单的办法么?
谁动了你的jar包 (二)
http://ilab.iteye.com/blog/1002629
之 通过反射动态改变类状态
谁动了你的jar包 (三)
http://ilab.iteye.com/blog/1006423
之 那个啥 jvmti !
分享到:
相关推荐
通过动态加载jar包的方式,反射调用内部方法
asm动态代理jar包,是java开发的好的工具类
可修改jar包内package包名,解决jar包不同版本冲突
这里是json开发需要的所有jar包文件哦~还有精心的json封装方法提示和最新jar包下载地址~现在拿出来分享啦!希望对大家有帮助! (1)json-lib最新版本可以从这个地方下载:...
android里面进行动画播放的jar包。
巴巴运动需要的jar包,好大呀,希望对大家有帮助
jar动态加载测试包,for Android开发系列之动态添加dex。
一个工具类实现了动态加载jar包 在不重启服务器的情况下,可以调用jar包的class
这个jar包可以实现对帆软报表里的类的方法进行拦截。
包括commons-logging commons-beanutils commons-lang ezmorph json-lib-2.4-jdk15 commons-collections-3.2.1的jar包,可以解决 org/apache/commons/lang/exception/NestableRuntimeException的问题
cglib-nodep-2.1_3.jar、asm-2.2.3.jar、asm-commons-2.2.3.jar、asm-util-2.2.3.jar四个包
struts2-jquery-plugin-3.1.1.jar; struts2-jquery-tree-plugin-3.1.1.jar; 两个jar包
动态代理cglibjar包和源码动态代理cglibjar包和源码动态代理cglibjar包和源码动态代理cglibjar包和源码动态代理cglibjar包和源码
该类加载器用于从指向 JAR 文件和目录的 URL 的搜索路径加载类和资源。如果不是以该字符结束,则认为该 URL 指向一个将根据需要打开的 JAR 文件pac
springboot动态加载jar包到容器中,并映射为接口对外提供服务
提供了JSP动态网站开发时及其它动态网站开发时用到的jar包,其中包括SQL数据库常用的jar包。
CGlib动态代理 jar包 用于动态代理技术
必须使用的jar包。 commons-collections.jar Apache Commons包中的一个,包含了一些Apache开发的集合类,功能比java.util.*强大 commons-lang.jar Apache Commons包中的一个,包含了一些数据类型工具类,是java....
JAVA动态加载JAR,zip包例子 有在项目中用到