世界はいろふである #irof_history

この記事はいろふ Advent Calendarの三日目の記事です。

一つ前は [twitter:@ayato_p]さんの あなただけの特別ないろふさん です。
一つ後は[twitter:@daiksy] さんの irof文が実装できたよ。そう、Scalaならね! です。

さて、各地で登録してしまったけれども何を書けばいいのかと頭を悩ませている人が多いと噂されるいろふAdvent Calendarも遂に三日目になりました。
いろふさんがJavaの達人ということで、Javaで世界がいろふさんであることを確かめようと思います。

    System.out.println("world".equals("irof"));

これを実行すると以下のようになりました。


見事に世界といろふさんが等しいと表示されましたね!
さすが私が愛用しているJVM。空気を読んでくれている。

これにて終了!















どうしてこうなったのか

実は上のコードの全体は以下のようになっていました。

    public static void main(String[] args) throws Exception {
        String s = "world";

        Field vf = String.class.getDeclaredField("value");
        vf.setAccessible(true);

        char[] cs = (char[]) vf.get(s);
        cs[0] = 'i';
        cs[1] = 'r';
        cs[2] = 'o';
        cs[3] = 'f';

        Field cf = String.class.getDeclaredField("count");
        cf.setAccessible(true);
        cf.setInt(s, 4);
        
        System.out.println("world".equals("irof"));
    }

はい。リフレクションでなんか怪しいことをしてますね。

Javaのシステムをたやすく壊すリフレクション

御存知の通り、Javaの文字列は文字列プールで管理されます。
文字列プールで管理しやすいようにStringはimmutableになっているわけですが、リフレクションを使うとimmutableであるはずのオブジェクトを変更することができてしまいます。
Stringプール内に保存された時は"world"だったはずが、中身としては"irof"になってしまっていたわけ。Javaのシステムを完全に悪用してますね。
いろふさんひどい。

リフレクション便利だからとりあえず使ってるという人は割と危険な機能であるので、こういった副作用もあり得るということを十分に理解した上で、活用して欲しいと思います。