2

Think about this sample code:

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

Suppose to run the code and within the try block an exception is raised. Execution flow goes into the catch block.

Here, I would like to copy the bytecode of the try block (maybe using ASM), apply some modifications to the bytecode (for example substitute stm2 with stm4) and execute the new piece of bytecode within the catch block.

Is this possible without compiling or loading the new bytecode, but just executing it like an interpreted language?

Thank you!

UPDATE

I know that I can write the right piece of code a priori. The question is not why, but how to do that and if it is possible.

Suppose that I have to compute the new try body dynamically and that I have to execute the new code within the same object (because of the local variables and class variables.)

Niko P
  • 41
  • 1
  • 3

4 Answers4

1

You'd probably be better off setting up a state machine and dynamically determining the next state. Something like:

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;
    }
}
TMN
  • 3,060
  • 21
  • 23
0

The following is by far the simplest

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

You can do what you suggest with ASM also. However, almost any alternative approach you take is likely to be simpler. ASM is usually the best option when you have little control over the code you are running (or rarely for performance) I would assume you have some control over the code.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Thanks. But let's suppose that have to compute the sequence stm1, stm4, stm3 dynamically, so I can't write it in the source code. – Niko P Sep 07 '11 at 15:31
  • 1
    It has to be written somewhere. Depending on where you get it from (and in what form) determines which is the simplest solution. – Peter Lawrey Sep 07 '11 at 15:33
  • Where can I write it? and how can I execute it. Think about that the code should access easily to local and class variables. – Niko P Sep 07 '11 at 15:44
  • When you write byte code it is for a whole class. (Even if that class have just one method) If you want easy access to fields they must be non-private or you have to re-write the whole class. See the ASM documentation for examples of how to write byte code using it. Once you have the byte code as a byte[] you can load it using defineClass. – Peter Lawrey Sep 07 '11 at 16:31
  • So, there's not a way to execute just a piece of bytecode extracted from the same class, right? (like executing a string of code in python) – Niko P Sep 07 '11 at 17:46
  • There isn't a simple way to dynamicly add code like that. Java has dynamic linking but its not that dynamic. You can use Javascript for example, but even a trivial expression can be 6 lines of boilerplate code. However, there is usually a way around it, but it depends on what you are actually trying to do. – Peter Lawrey Sep 07 '11 at 18:08
0

Not bytecode solution but Java :)

Maybe you can solve the problem by just typing the logic in the catch statement. One drawback will be that try catch block will be nested inside each and it will look ugly.

But it think it will be more maintainable that byte code loading.

0

You can decompose those individual statements into separate methods or classes and use Java reflection to call individual statements. Then it is up to you in what order you'd iterate trough those reflective calls.

Another option would be generating piece of code dynamically and execute it using one of the scripting languages supported for JVM, such as BeanShell, Groovy, JavaScript/Rhino, etc.

Eugene Kuleshov
  • 31,461
  • 5
  • 66
  • 67