0

When converting an Applet with the GWT framework I stumbled over this piece of code, where the author finds out the length of the array imageNames in a loop until an out-of-bounds exception occurs. It worked in the Applet, but not in GWT! After GWT compile the browser loops and does not show a reaction. Replacing Exception by JavaScriptException does not help.

    boolean error=false;
    int n_img = -1;
    String tmp;
    String[] imageNames;
    ...
    while (!error) {
        try {
            tmp = imageNames[(++n_img)];
        } catch (Exception e) {
            error = true;
        }
    }

Do you have any idea, how to catch the out-of-bounds-exception in GWT?

1
  • 1
    Well, that's the strangest loop I ever saw! This code can easily replaces with "for each". No need to handle exception! Or fori and using imageNames.lenght. And if you are not sure if imageNames is null, check it before. Commented May 19, 2018 at 9:21

2 Answers 2

1

This is one of the "shortcomings" of GWT - in the name of performance, extra emulation is not added to solve what should be an entirely avoidable bug. This is one of the most overt examples though.

First, recall that JS, for better or worse, is totally okay with you assigning values to indexes in Arrays that it may not have room for - you can use this to make a sparse array by skipping far past the end of the array, you can even assign to negative indexes.

On top of that Array feature, the Java array is implemented, and rather than read the expression array[n] and rewrite it to check n against the length before assigning (requiring two more checks for each read or write), it leaves it as-is.

And, since typically array operations like this are in a loop (such as in your code), this change would make every step through the loop faster, since it is trivial to do the bounds check as part of the loop condition.

And, typically Java users aren't writing array code on a regular basis, but leaning on ArrayList or the like - which does do these checks (though they can be disabled or reduced to improve runtime performance).

One more reason this isn't so bad: Sometimes you'd like to write in Java, and expect (not unreasonably) that you are actually acting on JS output. This allows for tricks like this:

array[array.length] = item;

to grow the array with each item. Obviously will fail in a JVM, but this is natural code to write in JS.

Finally, unless I'm very much mistaken, that isn't even a very optimized way to write that loop, even if throwing and catching that exception is cheaper than just doing a < check each step of the loop - we're still checking if !error is true each step! Instead, just make the loop run forever, and actually exit it, instead of requiring an additional boolean to track what the exception already tracks for you:

// just like the code in the question, do not do this, 
// this is just an example of how to get "too clever"
try {
  while (true) {
    tmp = imageNames[(++n_img)];
  }
catch (Exception ignore) {
  // do nothing, something "exceptional" but totally expected has occurred 
}
Sign up to request clarification or add additional context in comments.

Comments

0

So, thank you for the comment and the explaining answer. It will help me in further development. I now changed the faulty loop this way

   while (!error) {
        try {
            tmp = this.imageNames[(++n_img)];
            error=(n_img==imageNames.length); // correct severe bug
        } catch (Exception e) {

            error = true;
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.