たぷつきません

おなかがでてきた。もうたぷついてるやん。

BigDecimalのフォーマットのバグ

 BigDecimalのフォーマットに問題があって成果物をリリースできなかった。以下はJDK5_U12〜U14だと落ちるがJDK6_U03だと正常動作する。

public class BigDecimalTest {
  public static void main(String[] args) {
    System.out.println("9.4 -> " + String.format("%.0f", new BigDecimal(9.4)));
    System.out.println("9.5 -> " + String.format("%.0f", new BigDecimal(9.5)));
  }
}
9.4 -> 9
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:519)
	at java.lang.StringBuilder.append(StringBuilder.java:190)
	at java.util.Formatter$FormatSpecifier$BigDecimalLayout.layout(Formatter.java:3690)
	at java.util.Formatter$FormatSpecifier$BigDecimalLayout.<init>(Formatter.java:3610)
	at java.util.Formatter$FormatSpecifier.print(Formatter.java:3545)
	at java.util.Formatter$FormatSpecifier.print(Formatter.java:3460)
	at java.util.Formatter$FormatSpecifier.printFloat(Formatter.java:2716)
	at java.util.Formatter$FormatSpecifier.print(Formatter.java:2664)
	at java.util.Formatter.format(Formatter.java:2430)
	at java.util.Formatter.format(Formatter.java:2364)
	at java.lang.String.format(String.java:2558)
	at test.BigDecimalTest.main(BigDecimalTest.java:85)

 落ちる原因をおったところ、java.util.Formatter$FormatSpecifier$BigDecimalLayout.layout()に問題があることが分かった。1桁のバイト配列から2バイト読もうとして落ちていた。

JDK5
	if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) {
	    // count of padding zeros
	    int pad = scale - coeff.length;
	    if (pad >= 0) {
		// 0.xxx form
		mant.append("0.");
		dot = true;
		for (; pad > 0 ; pad--) mant.append('0');
		mant.append(coeff);
	    } else {
		// xx.xx form
		mant.append(coeff, 0, -pad);
		mant.append('.');
		dot = true;
		mant.append(coeff, -pad, scale);
	    }
	} else {
JDK6
	if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) {
	    // count of padding zeros
	    int pad = scale - coeff.length;
	    if (pad >= 0) {
		// 0.xxx form
		mant.append("0.");
		dot = true;
		for (; pad > 0 ; pad--) mant.append('0');
		mant.append(coeff);
	    } else {
		if (-pad < coeff.length) {
		    // xx.xx form
		    mant.append(coeff, 0, -pad);
		    mant.append('.');
		    dot = true;
		    mant.append(coeff, -pad, scale);
		} else {
		    // xx form
		    mant.append(coeff, 0, coeff.length);
			    for (int i = 0; i < -scale; i++) 
				mant.append('0');
		    this.scale = 0;
		}
	    }
	} else {

 JDK6で明らかにバグフィックスしている。JDK6で実行すると、「// xx form」のケースで処理されて正しい結果が得られる(しかし慌てたのかしらないけどインデントが汚くTABとスペースが先頭に混在してしまっている)。
なぜJDK5にも反映しないのさ。最近もU14出したばかりというのに。
→見つけた。http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6369500 レポートが1.5で起きているというのに、「mustangで対応したぜ!」…って、うぉい。
 SUNの中の人、これ読んでたら諸々対応してくれないでしょうか。(ああ、また言いっ放しで終わる)