Выполнение фрагмента байт-кода - PullRequest
2 голосов
/ 07 сентября 2011

Подумайте об этом примере кода:

...
try {
    stm1
    stm2
    stm3
} catch(){
    ...
}
...

Предположим, что для запуска кода и внутри блока try возникает исключение. Поток выполнения переходит в блок захвата.

Здесь я хотел бы скопировать байт-код блока try (возможно, используя ASM), применить некоторые модификации к байт-коду (например, заменить stm2 на stm4) и выполнить новый фрагмент байт-кода в блоке catch.

Возможно ли это без компиляции или загрузки нового байт-кода, а просто выполнения его как интерпретируемого языка?

Спасибо!

UPDATE

Я знаю, что могу написать правильный кусок кода априори. Вопрос не в том, почему, а в том, как это сделать и если это возможно.

Предположим, что мне нужно динамически вычислить новое тело попытки и мне нужно выполнить новый код в том же объекте (из-за локальных переменных и переменных класса.)

Ответы [ 4 ]

1 голос
/ 07 сентября 2011

Возможно, вам лучше настроить конечный автомат и динамически определить следующее состояние.Что-то вроде:

int nextState = 0;
while(nextState != -1) {
    try {
        switch(nextState) {
            case 0:
                stm1;
                ++nextState;
                break;
             case 1:
                stm2;
                ++nextState;
                break;
             case 2:
                stm3;
                nextState = -1;
                break;
             case 3:
                stm4;
                nextState = 2;
                break;
        }
    } catch (Exception err) {
        nextState = 3;
    }
}
0 голосов
/ 07 сентября 2011

Вы можете разложить эти отдельные операторы на отдельные методы или классы и использовать отражение Java для вызова отдельных операторов. Тогда вам решать, в каком порядке вы будете повторять эти рефлексивные вызовы.

Другим вариантом будет динамическое создание фрагмента кода и его выполнение с использованием одного из языков сценариев, поддерживаемых для JVM, таких как BeanShell, Groovy, JavaScript / Rhino и т. Д.

0 голосов
/ 07 сентября 2011

Не решение с байт-кодом, а Java:)

Возможно, вы можете решить проблему, просто набрав логику в операторе catch. Одним из недостатков будет то, что блок try catch будет вложен в каждый из них, и он будет выглядеть уродливо.

Но, думаю, будет проще поддерживать загрузку байтового кода.

0 голосов
/ 07 сентября 2011

Следующее является самым простым

try {
    stm1
    stm2
    stm3
} catch(){
    stm1
    stm4 // instead of stm2
    stm3
}

Вы также можете делать то, что предлагаете, с ASM. Тем не менее, почти любой альтернативный подход, который вы используете, вероятно, будет проще. ASM обычно является лучшим вариантом, когда у вас мало контроля над кодом, который вы запускаете (или редко для производительности), я бы предположил, что у вас есть некоторый контроль над кодом.

...