在工作中发现某个查询数据的接口,只要查询到名字 "9D" 的名字是会卡死。
接口运行60秒后,会出现Nginx超时界面,如下
<html>
<head>
<title>404 Not Found</title>
</head>
<body>
<center>
<h1>404 Not Found</h1>
</center>
<hr>
<center>nginx/1.17.3</center>
</body>
</html>
查询原因发现是
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch (Exception ex) {
return false;
}
}
......
try {
if(CommonUtility.isNumeric(str1)){
BigDecimal b1 = new BigDecimal(value1.toString());
}
} catch (Exception ex) {
e.printStackTrace
}
......
导致的,在 Double.parseDouble("9D")时,会认为D是类型而通过判定,到new BigDecimal("9D")时就会报错,e.printStackTrace会打印出大量错误信息,导致pipe通道被堵塞,整个接口卡死。
e.printStackTrace为什么会堵塞接口呢?
因为try catch后通过e.printStackTrace (System.err)打印异常堆栈,操作 系统的标准错误流最终指向pipe 管道,而输入时不能输出,导致pipe 被撑满了,最终导致整个服务的 线程无限阻塞。
所以最好所有异常处理的模块建议禁止使用e.printStackTrace和 System.err等标准错误流,最好不要用控制台输出语句,反正也看不到,而用log代替。
在此贴几个详细解释:
java-e.printStackTrace() 导致系统卡崩
字母后缀对于数字类型的判定:
对于Double.parseDouble的判断,Double.parseDouble("9D")可以通过判定 ,因为程序会以为Double类型或float类型,在做是否时数字判断的时候,要注意数字+D/F 的字符串。
去除d/f的影响:
if (str.contains("D")||str.contains("F")||str.contains("d")||str.contains("f")) {
return false;
}
Byte的B 和 Long的L均不会对此产生影响
如果使用其他数字类型的判断方式有没有这种问题就需要具体问题具体分析了