Я использую javassist, чтобы переписать метод с именем compile
(который принимает массив String в качестве аргумента): я создал новый метод, имеющий сигнатуру как метод compile
(это копия исходного), переименовал фактический метод compile
в compile$Impl
и добавлено несколько обращений к классу Mine.
Копия делается так:
CtMethod interceptMethod = CtNewMethod.copy(method, methodName, ctClass, null);
Javassist переписал код:
try {
com.company.CustomClass.instance().preintercept(this);
boolean result = compile$impl($$);
result = com.company.CustomClass.instance().dointercept(result, new Object[] { this , $1 });
return result;
} finally {
com.company.CustomClass.instance().postintercept(this);
}
Код записывается в переменную StringBuffer с именем body
, а содержимое более поздней переменной записывается как тело нового метода compile
следующим образом:
interceptMethod.setBody(body.toString());
ctClass.addMethod(interceptMethod);
Мои com.company.CustomClass
имеют методы, вызываемые новым методом compile
:
public Object dointercept(boolean retval, Object.. args) {
return (Boolean)returned;
}
public static synchronized CustomClass instance() {
// _instance is already instanciated when this method is called
return _instance;
}
public void preintercept(Object arg) {
// some stuff before
}
public void postintercept(Object arg) {
// some stuff after
}
При выполнении кода я получил verifyError:
java.lang.VerifyError: (class: org/eclipse/jdt/internal/compiler/batch/Main, method: compile signature: ([Ljava/lang/String;)Z) Expecting to find integer on stack
Я записал байт-код модифицированного класса на диск, чтобы попытаться обнаружить проблему. Вот что я получил для нового метода compile
:
public boolean compile(java.lang.String[] arg0) {
try {
0 invokestatic 2130; /* com.company.CustomClass.instance() */
3 aload_0;
4 invokevirtual 2134; /* void preintercept(java.lang.Object arg0) */
7 aload_0;
8 aload_1;
9 invokevirtual 2136; /* boolean compile$impl(java.lang.String[] arg0) */
12 istore_2;
13 invokestatic 2130; /* com.company.CustomClass.instance() */
16 iload_2;
17 iconst_2;
18 anewarray 4; /* new java.lang.Object[] */
21 dup;
22 iconst_0;
23 aload_0;
24 aastore;
25 dup;
26 iconst_1;
27 aload_1;
28 aastore;
29 invokevirtual 2140; /* java.lang.Object dointercept(boolean arg0, java.lang.Object[] arg1) */
32 istore_2;
33 iload_2;
34 istore_3;
35 goto 17;
38 iload_3;
39 ireturn;
}
finally { /* covers bytes 0 to 40 */
40 astore 4;
42 invokestatic 2130; /* com.company.CustomClass.instance() */
45 aload_0;
46 invokevirtual 2143; /* void postintercept(java.lang.Object arg0) */
49 aload 4;
51 athrow;
52 invokestatic 2130; /* com.company.CustomClass.instance() */
55 aload_0;
56 invokevirtual 2143; /* void postintercept(java.lang.Object arg0) */
59 goto -21;
}
}
Когда я прошел анализ типов байт-кода класса, ошибка была в строке 32 istore_2
инструкции. Вот анализ:
Type based analysis: compile([Ljava/lang/String;)Z
Offset Bytecode Stack before Stack after
----------------------------------------------------------------------------
0 invokestatic <empty> L
3 aload_0 L L, L
4 invokevirtual L, L <empty>
7 aload_0 <empty> L
8 aload_1 L L, L
9 invokevirtual L, L I
12 istore_2 I <empty>
13 invokestatic <empty> L
16 iload_2 L L, I
17 iconst_2 L, I L, I, I
18 anewarray L, I, I L, I, L
21 dup L, I, L L, I, L, L
22 iconst_0 L, I, L, L L, I, L, L, I
23 aload_0 L, I, L, L, I L, I, L, L, I, L
24 aastore L, I, L, L, I, L L, I, L
25 dup L, I, L L, I, L, L
26 iconst_1 L, I, L, L L, I, L, L, I
27 aload_1 L, I, L, L, I L, I, L, L, I, L
28 aastore L, I, L, L, I, L L, I, L
29 invokevirtual L, I, L L
32 istore_2 L <empty>
Error: Expecting to find I on stack, type on stack L.
33 iload_2 <empty> I
34 istore_3 I <empty>
35 goto <empty> <empty>
38 iload_3 <empty> I
39 ireturn I <empty>
40 astore L <empty>
42 invokestatic <empty> L
45 aload_0 L L, L
46 invokevirtual L, L <empty>
49 aload <empty> L
51 athrow L L
52 invokestatic <empty> L
55 aload_0 L L, L
56 invokevirtual L, L <empty>
59 goto <empty> <empty>
----------------------------------------------------------------------------
Но я не понимаю, почему возникает проблема с хранением int, зная, что я не использую целые числа (я уверен, что что-то упускаю).
Спасибо