好早之前总结的,测试代码找不到了,应该是在一个多线程无锁环境下使用同一个SimpleDateFormat对日期进行格式化,报错的错误。
SimpleDateFormat包含numberFormat字段,他是DecimalFormat类型,
DecimalFormat内部有个digitList是java.text.DigitList类型,
SimpleDateFormat的parse方法会转调DecimalFormat的parse方法,在DecimalFormat的parse方法内部有:longResult = digitList.getLong();这段代码,
DigitList的getLong
public final long getLong() {
// 省略部分 ... ...
StringBuffer temp = getStringBuffer();
temp.append(digits, 0, count); // 这个地方的count是个字段
for (int i = count; i < decimalAt; ++i) {
temp.append('0');
}
// 这一行抛出的异常, 推断temp是空字符串, 联系上下文代码进一步推断count=0, 猜测count被并发修改了,那应该在parse方法的longResult = digitList.getLong()这段代码之前有地方修改了count
return Long.parseLong(temp.toString());
}
在DecimalFormat的parse方法中:
public Number parse(String text, ParsePosition pos) {
... ...
if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) { // line: 1249
... ...
}
if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {
... ...
longResult = digitList.getLong(); // line: 1297
... ...
}
}
subparse方法如下:
private final boolean subparse(String text, ParsePosition parsePosition,
String positivePrefix, String negativePrefix,
DigitList digits, boolean isExponent,
boolean status[]) {
... ...
if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0, symbols.getInfinity().length())) {
... ...
} else {
// 这里修改了digits的count [注意: subparse倒数第三个实参名是digitList,而形参名是digits]
digits.decimalAt = digits.count = 0; // line: 1431
... ...
}
SimpleDateFormat线程不安全分析
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...