【发布时间】:2012-09-11 05:27:39
【问题描述】:
【问题讨论】:
-
你应该看看这篇文章:stackoverflow.com/questions/1054777/…
标签: java
【问题讨论】:
标签: java
除了字节码工程库,如果你的类有接口,你可以使用 Java 的 Proxy 类。
带接口:
public interface Foo {
void bar();
}
具体类:
class FooImpl {
public void bar() {
System.out.println("foo bar");
}
}
要处理调用的方法,请使用InvocationHandler:
class FooInvocationHandler implements InvocationHandler {
private Foo foo;
FooInvocationHandler(Foo foo) {
this.foo = foo;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
if (method.getName().equals("bar"))
System.out.println("foo me");
// return null if you don't want to invoke the method below
}
return method.invoke(foo, args); // Calls the original method
}
}
然后创建一个FooFactory 以使用Proxy 生成和包装FooImpl 实例:
public class FooFactory {
public static Foo createFoo(...) {
Foo foo = new FooImpl(...);
foo = Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
new FooInvocationHandler(foo));
return foo;
}
}
这将包装FooImpl 对象,这样:
Foo foo = FooFactory.createFoo(...);
foo.bar();
打印:
foo me
foo bar
这是 BCEL 库的替代方案,它可以执行此操作以及更多功能,包括从运行时信息生成类,但 BCEL 库不是本机的。 (Proxy 在 java.lang.reflect 中自 1.3 以来的所有内容。)
【讨论】:
进入一个已经加载的类?据我所知。
但是,您可能有兴趣生成一个新类。我看到两个选项:
像这样:
public static void printTest() {
System.out.println("Hey!");
}
然后查看字节码,看看 ConstantPool 中的“嘿!”存储,然后获取该方法的字节码,将其缓存到一个字节数组中,然后使用预定义的字节 + 常量池(您之前检查过)动态创建一个方法,并使用您的字符串修改常量池。尽管对于更复杂的方法,这会很快变得非常棘手(注意:可以做同样的事情来改变它调用的方法,或者它得到的字段,比如改成 err)
因为在我看来并没有什么好的选择,所以这些是你最好的选择
【讨论】: