2018-06-11(月) Java9、10でStringの+=に副作用があるバグ
■[java] Java9、10でStringの+=に副作用があるバグ
![はてなブックマーク - Java9、10でStringの+=に副作用があるバグ](data:image/gif;base64,R0lGODlhKQANAPEAAP9oZv/v7//Ly/+ZmCH5BAAAAAAALAAAAAApAA0AAAJWjI+py+0PkxgAiIjbCKLmv3Tb4QVeVwEGBQxXxaKlWV2kStN2QAkonaopfjeDh9UCpnKr1GhDNFqYnOO0iCAidxwKS2lDqmZBLuiMTieC7Lb7DZ+pQQUAOw==)
![Add Star Add Star](data:image/gif;base64,R0lGODlhEAAQAIABALrJ9f///yH5BAEAAAEALAAAAAAQABAAAAIojI+pm+APYQCIMlfZtLOvSEkexhmchXkjaHYlGpLpqrZNqbngnvd+AQA7)
Java 9、10でStringの+=にバグがあるということがStack OverFlowで報告されていました。
Why does array[idx++]+=”a” increase idx once in Java 8 but twice in Java 9 and 10? - Stack Overflow
どういうバグかというと「s[i++] += i + ""」のようなコードが正しく動かないというものです。
次のコードを実行してみます。
public class PlusEqual { public static void main(String[] args) { System.out.print(System.getProperty("java.version")); String[] s = {"aa", "bb"}; int i = 0; s[i++] += i + ""; System.out.printf(" %s %d%n", Arrays.toString(s), i); } }
Java 8では期待通りに動きます。
1.8.0_151 [aa1, bb] 1
ところが、JDK10.0.1では次のようになります。
10.0.1 [bb2, bb] 2
おもしろいのは、target=8とするとJDK10でもJava8と同じように動くところです。
10.0.1 [aa1, bb] 1
これは、「s[i++] += i + ""」が「s[i++] = s[i++] + i + ""」のように扱われていると考えることができます。
JDK11ea17で修正されています。JDK10.0.2はどうなるのかな。バックポートはされる予定。Java9はメンテナンスリリースは公開されないので、そのまま。
JDK-8204322 ”+=” applied to String operands can provoke side effects - Java Bug System
で、このバグレポートはJEP280に関連づけられてるので、+演算子をdynamicInvoke使う実装にしたときにエンバグしたっぽいですね。
JEP 280: Indify String Concatenation
Java8までのJVMでは もちろん文字列結合のdynamicInvokeに対応していないので、target=8としたときには問題が発生しない、と。
なので、Java9やJava10.0.1でtarget=8したくない場合は-XDstringConcat=inline をつけてコンパイルすれば問題を回避することができるようです。