2009-05-10 15:16 | 菜鸟
Test.main() inserts a call to println() in the method body of say() in Hello. Then it constructs an instance of the modified Hello class and calls say() on that instance.
Note that the program above depends on the fact that the Hello class is never loaded before toClass() is invoked. If not, the JVM would load the original Hello class before toClass() requests to load the modified Hello class. Hence loading the modified Hello class would be failed (LinkageError is thrown). For example, if main() in Test is something like this:
public static void main(String[] args) throws Exception {
Hello orig = new Hello();
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("Hello");
:
}
then the original Hello class is loaded at the first line of main and the call to toClass() throws an exception since the class loader cannot load two different versions of the Hello class at the same time.
If the program is running on some application server such as JBoss and Tomcat, the context class loader used by toClass() might be inappropriate. In this case, you would see an unexpected ClassCastException. To avoid this exception, you must explicitly give an appropriate class loader to toClass(). For example, if bean is your session bean object, then the following code:
CtClass cc = ...;
Class c = cc.toClass(bean.getClass().getClassLoader());
would work. You should give toClass() the class loader that has loaded your program (in the above example, the class of the bean object).
toClass() is provided for convenience. If you need more complex functionality, you should write your own class loader.
回复 更多评论