12.01.2019

Странности Java-оптимизатора

Короче, сижу себе такой, никого не трогаю, пишу маленькую программку под андроид, на яве значит.
И там у меня должен получится вот такой фрагмент кода:

while (i < raw_data.length())
  i = parseName(raw_data, i+1, j++);
 
Собственно, анализирую и разбираю строку raw_data. По идее, оптимизатор должен сам вынести из цикла инварианты. Но не факт, тем более что вызывается метод, в котором вдруг что-нибудь со строкой происходит.
Поэтому "оптимизирую" ручками. Ну вот люблю я какую-нибудь совершенно не нужную мелочь соптимизировать. )
int k = raw_data.length();
while (i < k)
  i = parseName(raw_data, i+1, j++);

И ничего бы я так и не заметил, если бы не потребовалась отладка. А под отладкой я вижу, что перебираются не только две последние строчки цикла, но и первая, которую я специально из цикла вынес, для оптимизации.

Не знаю, чем это объяснить. Может, очень глубокой оптимизацией? Скорее всего длина строки хранится в поле объекта, оптимизатор пишет эффективное обращение к ней напрямую, без вызова метода, а переменную k вообще не использует? Зачем тогда в отладчике показывает посещение первой строчки?

Но это предположение не верно. В ходе отладке выясняется, где находится ошибка. Правильный код должен выглядеть вот так:
int k = raw_data.length()-1;
while (i < k)
  i = parseName(raw_data, i+1, j++);

И в этом случае первая строка кода тоже попадает в цикл!
Так что дело тут не в оптимизации, а, похоже, в параноидальной заботе о корректности кода со стороны Java-компилятора. А вдруг в методе parseName что-нибудь вытворят с raw_data? Поэтому загоним инвариант обратно в цикл.
Но, уважаемые разработчки Java, я специально вынес длину строки в отдельную переменную, что бы не делать лишних вычислений, потому что уверен в том, что parseName raw_data не меняет!

Вот такие чудеса! Или я просто Java готовить не умею?