An infinite loop keeps executing because its exit condition never becomes false. In Java, this often comes from a malformed classic `for` loop, where a nested loop tests or updates the outer counter instead of its own. The result may be an apparent hang, or code that only terminates when an incidental `break` runs. section 3.4
for (int i = 0; i < 10; i++) {
for (int j = 0; i < 10; j++) { #1
// use i and j
}
}
The inner loop tests `i`, but only `j` changes. While `i < 10` remains true, the inner loop has no natural termination path. section 3.4
A loop can also run forever when its body makes no progress toward ending it. Recomputing the same value on every iteration is idempotent: if the condition remains true, the next iteration repeats exactly the same attempt. Progress must change relevant state, such as advancing a suffix counter. section 3.8
static String makeUniqueId(String id, Set<String> usedIds) {
int i = 1;
String uniqueId = id;
while (usedIds.contains(uniqueId)) {
uniqueId = id + "_" + i;
}
return uniqueId;
}
When `id` and `i` remain unchanged, a used identifier repeatedly produces the same `_1` candidate. Incrementing `i` in the loop body makes later suffixes reachable. section 3.8
Avoid and investigate infinite loops by checking:
- Match each loop condition and update with the counter that loop owns, especially in nested loops. section 3.4
- Verify that every continuing path changes state relevant to termination; do not rely on a conditional `break` to conceal a faulty loop header. section 3.4 section 3.8
- Treat inclusive `<=` bounds cautiously when the upper bound can be `Integer.MAX_VALUE` or `Long.MAX_VALUE`, as counter overflow can make the condition stay true. section 3.7
- Use static-analysis warnings as leads, not proof: IntelliJ IDEA can find simple always-true conditions and idempotent bodies, but may miss paired header mistakes or cases requiring interprocedural analysis. section 3.4 section 3.8
Overflow at an inclusive upper bound
`for (int i = lo; i <= hi; i++)` becomes nonterminating when `hi` is `Integer.MAX_VALUE`: after reaching the maximum value, `i++` overflows to a negative number and still satisfies `i <= hi`. Add a lower-bound guard, test the corner case, or consider `IntStream.rangeClosed(lo, hi)` when its overhead is acceptable. section 3.7


