I am quite convinced that here
final int i;
try { i = calculateIndex(); }
catch (Exception e) { i = 1; }
i cannot possibly have
I think the JVM is, sadly, correct. While intuitively correct from looking at the code, it makes sense in the context of looking at the IL. I created a simple run() method that mostly mimics your case (simplified comments here):
0: aload_0
1: invokevirtual #5; // calculateIndex
4: istore_1
5: goto 17
// here's the catch block
17: // is after the catch
So, while you can't easily write code to test this, because it won't compile, the invoke of the method, the store the value, and the skip to after the catch are three separate operations. You could (however unlikely that may be) have an exception occur (Thread.interrupt() seems to be the best example) between step 4 and step 5. This would result in entering into the catch block after i has been set.
I'm not sure you could intentionally make that happen with a ton of threads and interrupts (and the compiler won't let you write that code anyway), but it is thus theoretically possible that i could be set, and you could enter in the exception handling block, even with this simple code.