Java’s silent killer – Integer Overflow, Careful !
Believe it or not, Java contains Integer buffer overflow as well. I’m not sure is this the correct word to describe it or not, may be you can suggest some 🙂
OK, please take a look at below program, this program print the number of microseconds in a day.
public class JavaLongOverflow {
public static void main(String[] args) {
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
System.out.println("MICROS_PER_DAY : " + MICROS_PER_DAY);
}
}
Result
MICROS_PER_DAY : 500654080
Oh.. the answer is 500654080. Wait.. is the answer correct? The correct answer should be 86400000000 !!! Why Java will give me an inaccurate result? where is this number come from? What happened exactly?
I do believe this is cause by an “int” overflow. Yes, the “long MICROS_PER_DAY” variable has enough space to fit in large number like 86400000000, but it doesn’t fit in an “int”! The maximum number of an “int” is 2147483647. Look careful of the program above, the whole arithmetic is in “int”, the result promoted to a long and assign to “long MICROS_PER_DAY” variable. According to [JLS 5.1.2], the promotion from int to long is cited as widening primitive conversion which preserves the (incorrect) numerical value.
However we can avoid above silent killer overflow by explicit the “long” in the first integer to force whole operation become a long arithmetic.
public class JavaLongOverflow {
public static void main(String[] args) {
final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
System.out.println("MICROS_PER_DAY : " + MICROS_PER_DAY);
}
}
Result
MICROS_PER_DAY : 86400000000
Above program prints 86400000000 as expected
Conclusion
This bug is so so difficult to detect or aware of. Sometime it’s even impossible to detect it. If someone make this kind of mistake in financial system, i just cant imaging the consequent. My only advice is to explicitly cast the primitive type when deal with calculation of two different type of primitive type. Always avoid to automatically widening primitive conversion in any calculation.
The conclusion is: you don’t know what a buffer overflow is.
i think the title better changed to interger overflow in Java
http://en.wikipedia.org/wiki/Integer_overflow
Hi Mkyong,
Do you know any way to prevent the overflow from happening (like automatically raising an ArithmeticException or something like this)?
I could use BigInteger everywhere but it is a bit clumsy.