首先铺垫一下,这段代码的输出是什么?
public static void main(String []args){ System.out.println(Integer.MAX_VALUE + 1); }
很多人可能很快就能答出来,正确答案是:-2147483648
那么接下来看这段代码:
public static void main(String []args){ Long total = Long.MAX_VALUE; for (int i = 0; i < total; i++) { System.out.println(i); } }
乍看之下似乎没啥大毛病,但是结合前面的铺垫,就会发现:
当 i 增长到 Integer.MAX_VALUE 的时候,“奇迹”出现了。接下来,下一个 i 值变为了 -2147483648。跟 total 一比,还是小,于是循环继续。
周而复始,这个循环就永远停不下来了。
当然,这里因为我的简化,还是能比较容易的看出这个死循环的。而实际使用中,这个 total 的取值往往是外部带来的。正常情况下,可能外部取值不会大过Integer.MAX_VALUE ,也就是 2147483648。但是当恶意请求出现或者是正常请求越过边界之后,问题就出现了。
所以当我们定义循环变量的时候,一定要小心。循环变量本身的取值范围一定要大于判断条件。简单来说,在上面的例子中,i 的取值必须要能够大于等于 total 可能的最大值。也就是说,在 total 是 Long 的情况下,i 也必须至少定义为 Long,才不会出现问题。
简单总结一下,就是对于控制循环的变量定义一定要非常谨慎。否则极有可能出现类似很难测出的 Bug,导致各种各样的问题。
记一则由于整数溢出导致的教科书级的死循环 by 桔子小窝 is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.