Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with Try/Catch Exceptions in Java bytecode? ("stack height inconsistent")

I am trying to do some error handling in java bytecode. I first tried to implement some catch-like subroutines, where I would check for the error condition, and jump to the appropriate subroutine, a little like:

  iconst_1
  iconst_0
  dup
  ifeq calldiverr
  goto enddivtest
calldiverr:
  jsr divError
enddivtest:
  idiv

...More instructions...

divError:
  getstatic java/lang/System/out Ljava/io/PrintStream;
  ldc "Oh dear you divided by 0!"
  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V

The problem with the above is that when I have multiple instructions that jump to this subroutine, I get an error message when running the bytecode, saying that the stack height is inconsistent.

Perhaps using exceptions is the best way to get around this?

From some googling I have found that you can create instances of Exception classes and initialise them with something like:

new java/lang/Exception
dup
ldc "exception message!"
invokespecial java/lang/Exception/<init>(Ljava/lang/String;)V

I have also found that you can throw them with athrow and this seems ok.

What is confusing me however is exactly how exceptions are caught. There seems to be a magical "Exception table" which glues the throwing and catching of exceptions together, but I do not know how to define one of these when writing bytecode from scratch (and assembling using Jasmin). Can somebody tell me the secret of creating an exception table? And possibly give me an example of exception handling that will assemble with jasmin?

like image 836
Jack Avatar asked Dec 12 '11 22:12

Jack


People also ask

Does try catch slow down Java?

In general, wrapping your Java code with try/catch blocks doesn't have a significant performance impact on your applications. Only when exceptions actually occur is there a negative performance impact, which is due to the lookup the JVM must perform to locate the proper handler for the exception.

How many errors a catch block can handle at a time?

At a time only one exception occurs and at a time only one catch block is executed.

Which is the correct try block handling?

Java try block It must be used within the method. If an exception occurs at the particular statement in the try block, the rest of the block code will not execute. So, it is recommended not to keep the code in try block that will not throw an exception. Java try block must be followed by either catch or finally block.

Is try catch faster than if?

If you've one if/else block instead of one try/catch block, and if an exceptions throws in the try/catch block, then the if/else block is faster (if/else block: around 0.0012 milliseconds, try/catch block: around 0.6664 milliseconds). If no exception is thrown with a try/catch block, then a try/catch block is faster.


1 Answers

In the end I came up with a better solution than jsr - defining a method using .method in Jasmin. I just used invokestatic to call my error handler once I had detected the error.

For those looking for actual exception handling - I think that defining the exception table in Jasmin may be done using .catch, but I haven't looked into it as the method definition solved my problem.

Edit:

I did have to look at .catch in the end, and found it is really easy to use. It's documented here.

like image 131
Jack Avatar answered Oct 06 '22 04:10

Jack