The reason is compiler will consider that there may be a chance that b is being changes from its previous value to some other value by some other part of your program or thread, Even though your program is not actually changing b but compiler will not detect it at compile time.
Clarification could be just make b as final & see you will get the same error because compiler will notice that b is final & can not be changed by other part of program so will consider false as final value of b & thus will produce error .
final boolean b = false;
for(;b;)
System.out.println("NO error"); //error: unreachable statement