私はjavassistを使い慣れていません。しかし、他にも多くのことが働いていないようです。 javassistで動作しない空のコンストラクタ(java)を作成します。
Iは、クラス -
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();
}
Iは、コードが実行されたときにイベントを発生するために、方法にバイトコードを追加するには、このコードを使用するにコードを注入する方法を作りました。
最後にクラス(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