我是javassist的新手,開始惹惱它,並得到一些工作。但是,還有很多其他的東西似乎並不奏效。用javassist創建空的構造函數(java)不能上班
我做了注入代碼的方法到類 -
public static void editMethodAddEvent(CtClass target, MethodInfo method, CtClass eventClass, int start, int[] bytes, int stacksize, String constructorParameters) throws BadBytecode, NotFoundException, CannotCompileException {
target.defrost();
CodeAttribute codeAttribute = method.getCodeAttribute();
CodeIterator iterator = codeAttribute.iterator();
int classID = method.getConstPool().addClassInfo(eventClass);
int constrnatID = method.getConstPool().addNameAndTypeInfo("<init>",constructorParameters);
int constructID = method.getConstPool().addMethodrefInfo(classID,constrnatID);
int callnatID = method.getConstPool().addNameAndTypeInfo("call","()V");
int callID = method.getConstPool().addMethodrefInfo(classID,callnatID);
iterator.insertGap(start,bytes.length);
for (int i = 0; i < bytes.length; i++) {
int byteCode = bytes[i];
if (byteCode >= 0) {
iterator.writeByte(byteCode, start+i);
} else if (byteCode == -1) {
iterator.writeByte(classID,start+i);
} else if (byteCode == -2) {
iterator.writeByte(constructID, start+i);
} else if (byteCode == -3) {
iterator.writeByte(callID, start+i);
}
}
if(stacksize > codeAttribute.getMaxStack())
codeAttribute.setMaxStack(stacksize);
target.toClass();
}
我使用此代碼的字節代碼添加到一個方法,觸發事件是運行代碼時。
當我在最後編譯類(target.toClass())時,它沒有錯誤(並且工作正常)。
但是,當我添加一個方法(在這種情況下是空的構造函數),使用下面的代碼,它的錯誤。
public static Class addEmptyConstructor(Class clazz) throws NotFoundException, CannotCompileException {
CtClass ctClass = ClassPool.getDefault().getCtClass(clazz.getName());
ctClass.defrost();
ClassFile classFile = ctClass.getClassFile();
MethodInfo newMethod = new MethodInfo(classFile.getConstPool(), "<init>", "()V");
newMethod.setCodeAttribute(new CodeAttribute(classFile.getConstPool(),1,1,new byte[]{0,0,0,0,0},new ExceptionTable(classFile.getConstPool())));
CodeIterator iterator = newMethod.getCodeAttribute().iterator();
iterator.writeByte(42, 0);
iterator.writeByte(183,1);
iterator.writeByte(0,2);
iterator.writeByte(1,3);
iterator.writeByte(177,4);
classFile.addMethod(newMethod);
return ClassPool.getDefault().toClass(ctClass);
}
給出的錯誤是:
javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "mod/TestClass"
at javassist.util.proxy.DefineClassHelper.toClass2(DefineClassHelper.java:140)
at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:95)
at javassist.ClassPool.toClass(ClassPool.java:1143)
at javassist.ClassPool.toClass(ClassPool.java:1106)
at javassist.ClassPool.toClass(ClassPool.java:1064)
at mod.edit.MethodEdit.addEmptyConstructor(MethodEdit.java:113)
<other nonrelevant stuff...>
Caused by: java.lang.LinkageError: loader (instance of
sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for
name: "haven/mod/TestClass"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javassist.util.proxy.DefineClassHelper.toClass3(DefineClassHelper.java:152)
at javassist.util.proxy.DefineClassHelper.toClass2(DefineClassHelper.java:134)
... 10 more
我的目標是創建一個空的構造函數,這樣我可以不投入參數創建任何對象的實例。具體來說,我有很多種事件,有參數。我不想在編譯時訪問這個構造函數。因此,我嘗試在運行時使用javassist添加構造函數,並拒絕編譯。如果我簡單地編輯一個方法,它不會大驚小怪,但如果我添加一個方法,它似乎拒絕做我想要的。我該如何解決這個問題?我一直在嘗試超過16個小時,研究,測試不同的代碼,並且無法獲得任何工作。請幫忙!!!!
你確定你沒有添加一個空構造函數給已經有一個空的構造函數的類嗎? – rakwaht
是的,我現在只是在某些地方調用此方法進行測試。通過字節碼或簡化的CtMethod或CtConstructor方法添加任何方法都會出現問題。感謝您試圖幫助! – PoisonedPorkchop
我有一個在TestClass中有參數和冗餘代碼的構造函數,所以編譯器不會創建默認的。 – PoisonedPorkchop