異常
線上收到告警, 有以下異常
java.lang.ArithmeticException: input is infinite or NaN
at com.google.common.math.DoubleMath.roundIntermediate(DoubleMath.java:59)
at com.google.common.math.DoubleMath.roundToLong(DoubleMath.java:156)
.......................
代碼
對應的業務代碼如下:
public static Long formatLongDefaultNegativeOne(Object obj) {
String objStr = String.valueOf(obj);
return !StringUtils.isBlank(objStr) &&
!objStr.equals("NaN") &&
!objStr.equals("Infinity") &&
!objStr.equals("null") ?
DoubleMath.roundToLong(Double.valueOf(String.valueOf(obj)), RoundingMode.HALF_EVEN) :
-1L;
}
拋出異常的地方做了如下判斷:
......
if (!isFinite(x)) {
throw new ArithmeticException("input is infinite or NaN");
}
......
......
//判斷是否在有限範圍內
static boolean isFinite(double d) {
return getExponent(d) <= MAX_EXPONENT;
}
getExponent(d)
是獲取當前 double
值的指數 . MAX_EXPONENT
是Double
最大值的指數 .
getExponent(d)
的方法註釋中有以下說明:
If the argument is NaN or infinite, then the result is Double.MAX_EXPONENT + 1.
If the argument is zero or subnormal, then the result is Double.MIN_EXPONENT -1.
判斷不在有效範圍內的, 只有兩種情況 , double
值是 NaN
或Infinity
.
分析
主要邏輯都在這行代碼中:
DoubleMath.roundToLong(Double.valueOf(String.valueOf(obj)))
從上面的異常中可以得知 , DoubleMath.roundToLong
方法得到是 NaN
或 Infinity
. 即 Double.valueOf() == NaN || Double.valueOf() == Infinity
.
業務方法的這個代碼 formatLongDefaultNegativeOne(Object obj)
是從上游獲取的數值 , 業務上已經限定了只能是數值類型. 對於從上游得到的數值 , 理論上是隻有這幾種情況了.
- null
- NaN
- Infinity
- 正常數值
對於前三種 , 邏輯上已經做了判斷 , 但結果還是拋出了異常 . 說明數值不在上面四種情況裏 .
當前也沒有想法具體是什麼樣的數值才能導致這個異常 . 由於缺少線上數據的支撐 , 無法繼續下去 . 只能後面再解決定位了.
未完待續.......
如果文章有幫助到您,請點個贊,您的反饋會讓我感到文章是有價值的