最近测试在做压测的时候,发现一个接口偶尔会报错,对于有错必查的程序员来说,一定要看看是什么问题。查看日志发现这样的错误。
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:601)
at java.lang.Long.parseLong(Long.java:631)
at java.text.DigitList.getLong(DigitList.java:195)
at java.text.DecimalFormat.parse(DecimalFormat.java:2051)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.cimu.util.date.DateUtils.getDateFormat(DateUtils.java:107)
at com.cimu.util.date.DateUtils.getNowDate(DateUtils.java:167)
问题排查
查看代码,确实有一个地方调用了时间转换的方法,但是那个方法是项目中使用的工具类,使用了 java.text 包下的 SimpleDateFormat 来进行转换;代码如下:
public final static String DATE_PATTERN = "yyyy-MM-dd";
// 日期格式化
private static DateFormat dateFormat = null;
static {
dateFormat = new SimpleDateFormat(DATE_PATTERN);
}
public static Date getNowDate() {
return DateUtils.getDateFormat(dateFormat.format(new Date()));
}
public static Date getDateFormat(String date) {
try {
return dateFormat.parse(date);
} catch (ParseException e) {
log.error("转换报错",e);
}
return null;
}
在业务代码里,使用了 getNowDate()方法。找到问题代码了,那是什么原因会报错呢?
问题分析
从报错日志看,应该是在 Long 类的第 601 行报错,
发现这里就一行代码。就是抛出 NumberFormatException 异常。
在往上找,找到 Long 类的第 631 行,
这里就是调用了 Long 类的 parseLong 方法。跟着错误日志接着往上找。
找到 DigitList 类
看到这里,应该是 temp.toString()传了一个空字符串,导致 Long 那边的方法报错。
应该是 192 行的 for 循环没有执行,查看 count,decimalAt 的属性,在高并发下会存在问题。
问题解决
查到原因了,那么如何解决呢?
1、在 getNowDate()方法前面加上 synchronized
该方法会影响性能
2、SimpleDateFormat 不使用全局静态变量,每次调用都生成一个,这样会增加开销。
3、使用 commons.lang3 下的 DateUtils 和 DateFormatUtils 方法。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于