Javaは、intまたはlongプリミティブ型の整数オーバーフローについては何もせず、正および負の整数によるオーバーフローを無視します。
この回答では、最初に整数オーバーフローについて説明し、式の評価で中間値を使用した場合でも発生する例を示し、次に整数オーバーフローを防止および検出するための詳細な手法を提供するリソースへのリンクを示します。
予期しないまたは検出されないオーバーフローを引き起こす整数演算および式は、一般的なプログラミングエラーです。予期しない、または検出されない整数オーバーフローも、特に配列、スタック、リストオブジェクトに影響を与えるため、悪用可能な既知のセキュリティ問題です。
オーバーフローは、正または負の方向に発生する可能性があり、正または負の値は、問題のプリミティブタイプの最大値または最小値を超えます。オーバーフローは、式または演算の評価中に中間値で発生し、最終値が範囲内であると予想される式または演算の結果に影響を与える可能性があります。
負のオーバーフローは、誤ってアンダーフローと呼ばれることがあります。アンダーフローは、表現が許可するよりも値がゼロに近い場合に発生します。アンダーフローは整数演算で発生し、予期されています。整数のアンダーフローは、整数の評価が-1から0または0から1の間になる場合に発生します。小数の結果は0に切り捨てられます。これは正常であり、整数演算で予期され、エラーとは見なされません。ただし、コードが例外をスローする可能性があります。1つの例は、整数アンダーフローの結果が式の除数として使用されている場合の「ArithmeticException:/ by zero」例外です。
次のコードを検討してください。
int bigValue = Integer.MAX_VALUE;
int x = bigValue * 2 / 5;
int y = bigValue / x;
その結果、xには0が割り当てられ、それに続くbigValue / xの評価では、yに値2が割り当てられる代わりに、例外「ArithmeticException:/ by zero」(つまり、ゼロで除算)がスローされます。
xの予想結果は858,993,458であり、これは最大のint値である2,147,483,647未満です。ただし、Integer.MAX_Value * 2の評価からの中間結果は、4,294,967,294となり、これは最大のint値を超え、2の補数整数表現によれば-2です。-2 / 5の後続の評価は0に評価され、xに割り当てられます。
xを計算するための式を、評価するときに乗算する前に除算する式に次のコードを再配置します。
int bigValue = Integer.MAX_VALUE;
int x = bigValue / 5 * 2;
int y = bigValue / x;
その結果、xには858,993,458が割り当てられ、yには2が割り当てられますが、これは予期されていることです。
bigValue / 5の中間結果は429,496,729であり、intの最大値を超えません。429,496,729 * 2の後続の評価は、intの最大値を超えず、期待される結果がxに割り当てられます。yの評価はゼロで除算されません。xとyの評価は期待どおりに機能します。
Java整数値は、2の補数符号付き整数表現として格納され、それに従って動作します。結果の値が最大または最小の整数値よりも大きいまたは小さい場合、代わりに2の補数の整数値が生成されます。2の補数の動作を使用するように明確に設計されていない状況、つまり最も一般的な整数演算の状況では、結果の2の補数の値により、上記の例で示したようにプログラミングロジックまたは計算エラーが発生します。Wikipediaの優れた記事では、2の補数の2進整数についてここで説明しています。2の補数-ウィキペディア
意図しない整数オーバーフローを回避するための手法があります。Techinquesは、事前条件テスト、アップキャスト、およびBigIntegerを使用するものとして分類できます。
事前条件テストでは、算術演算または式に入る値を調べて、それらの値でオーバーフローが発生しないことを確認します。プログラミングと設計では、入力値がオーバーフローを引き起こさないことを確認するテストを作成し、オーバーフローを引き起こす入力値が発生した場合の対処法を決定する必要があります。
アップキャスティングでは、より大きなプリミティブ型を使用して算術演算または式を実行し、結果の値が整数の最大値または最小値を超えているかどうかを判断します。アップキャストを使用しても、演算または式の値または中間値がアップキャストタイプの最大値または最小値を超えてオーバーフローが発生する可能性があり、これも検出されず、予期しない望ましくない結果が発生します。分析または事前条件により、アップキャストなしでの防止が不可能または実用的でない場合、アップキャストでオーバーフローを防止できる可能性があります。問題の整数がすでに長いプリミティブ型である場合、Javaのプリミティブ型ではアップキャストできません。
BigInteger手法は、BigIntegerを使用するライブラリメソッドを使用した算術演算または式にBigIntegerを使用することで構成されます。BigIntegerはオーバーフローしません。必要に応じて、使用可能なすべてのメモリを使用します。その算術メソッドは通常、整数演算よりもわずかに効率が悪いだけです。BigIntegerを使用した結果が整数の最大値または最小値を超える可能性がありますが、結果に至るまでの算術演算でオーバーフローは発生しません。BigIntegerの結果が、intやlongなどの目的のプリミティブな結果タイプの最大値または最小値を超えている場合は、プログラミングと設計でどうするかを決定する必要があります。
カーネギーメロンソフトウェアエンジニアリングインスティテュートのCERTプログラムとOracleは、安全なJavaプログラミングのための一連の標準を作成しました。標準には、整数オーバーフローを防止および検出するための技術が含まれています。この標準は、無料でアクセスできるオンラインリソースとしてここに公開されています。Java用のCERT Oracle Secure Coding Standard
整数オーバーフローを防止または検出するためのコーディング手法の実用的な例を説明し、含む標準のセクションは、NUM00-Jです。整数オーバーフローを検出または防止する
Java用のCERT Oracle Secure Coding StandardのブックフォームとPDFフォームも利用できます。