Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Programs must not allow mathematical operations to exceed the integer ranges provided by their primitive integer data types. According to the Java Language Specification (JLS), §4.2.2, "Integer Operations" [JLS 2005]:

The built-in integer operators do not indicate overflow or underflow in any way. Integer operators can throw a NullPointerException if unboxing conversion of a null reference is required. Other than that, the only integer operators that can throw an exception are the integer divide operator / and the integer remainder operator %, which throw an ArithmeticException if the right-hand operand is zero, and the increment and decrement operators ++ and -- which can throw an OutOfMemoryError if boxing conversion is required and there is insufficient memory to perform the conversion.

The integral types in Java, representation, and inclusive ranges are shown in the following table taken from the JLS, §4.2.1, "Integral Types and Values" [JLS 2005]:

Type

Representation

Inclusive Range

byte

8-bit signed two's-complement

-128 to 127

short

16-bit signed two's-complement

-32,768 to 32,767

int

32-bit signed two's-complement

-2,147,483,648 to 2,147,483,647

long

64-bit signed two's-complement

-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

char

16-bit unsigned integers representing UTF-16 code units

\u0000 to \uffff (0 to 65,535)

...

When a mathematical operation cannot be represented using the supplied integer types, Java's built-in integer operators silently wrap the result without indicating overflow. This can result in incorrect computations and unanticipated outcomes. Failure to account for integer overflow has resulted in failures of real systems, for example, when implementing the compareTo() method. The meaning of the return value of the compareTo() method is defined only in terms of its sign and whether it is zero; the magnitude of the return value is irrelevant. Consequently, an apparent but incorrect optimization would be to subtract the operands and return the result. For operands of opposite signs, this can result in integer overflow, consequently violating the compareTo() contract [Bloch 2008, Item 12].

Comparison of Compliant Techniques

...

Operations on objects of type AtomicInteger suffer from the same overflow issues as other integer types. The solutions are generally similar to the solutions already presented; however, concurrency issues add additional complications. First, potential issues with time-of-check, time-of-use (TOCTOU) must be avoided; see rule VNA02-J. Ensure that compound operations on shared variables are atomic for more information. Second, use of an AtomicInteger creates happens-before relationships between the various threads that access it. Consequently, changes to the number of accesses or order of accesses can alter the execution of the overall program. In such cases, you must either choose to accept the altered execution or carefully craft your implementation to preserve the exact number of accesses and order of accesses to the AtomicInteger.

...

The two arguments to the compareAndSet() method are the expected value of the variable when the method is invoked and the intended new value. The variable's value is updated only when the current value and the expected value are equal [API 2006]. Refer to rule VNA02-J. Ensure that compound operations on shared variables are atomic for more details.

...

Note these methods are deprecated in API level 18 and replaced by getAvailableBlocksLong() and getBlockSizeLong().

Bibliography

 

...

Rule 03: Numeric Types and Operations (NUM)      Rule 03: Numeric Types and Operations (NUM)Image Added      Image Added