ボクシングとキャッシュ
Integerのキャッシュ
int がボクシングされると java.lang.Integer になりますが、このとき Integer.valueOf(int) が使われます。 このことは次のようなボクシングされるコードを書いてコンパイルしてからjavapすればよく分かります。
public class IntBoxingSample {
public Integer boxing(int i) {
return i;
}
}
javapしてみた結果は次の通り。
Compiled from "IntBoxingSample.java"
public class IntBoxingSample {
public IntBoxingSample();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public java.lang.Integer boxing(int);
Code:
0: iload_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: areturn
}
で、この Integer.valueOf(int) ですが、 -128 から 127 までの範囲はキャッシュされます。
このことは 言語仕様の5.1.7 や Integer.valueOf(int)のJavadoc に書かれています。
でもって、OpenJDKのコードを見た感じ、 java.lang.Integer.IntegerCache.high というシステムプロパティでキャッシュする範囲を変更できそうです。
というわけで次のようなコードを書いてコンパイルして普通に実行すると false と表示されますが、 -Djava.lang.Integer.IntegerCache.high=1000 という風にシステムプロパティを設定して実行すると true と表示されます。
public class Sample {
public static void main(String[] args) {
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b);
}
}
実行結果は次の通り。
% java Sample
false
% java -Djava.lang.Integer.IntegerCache.high=1000 Sample
true
他のプリミティブも見てみた
Byte 、 Short 、 Long は Integer と同じく -128 から 127 までキャッシュされていました。 ただしキャッシュの範囲は変更できません。
- Byte.valueOf(byte)のコード と Byteのキャッシュ構築コード
- Short.valueOf(short)のコード と Shortのキャッシュ構築コード
- Long.valueOf(long)のコード と Longのキャッシュ構築コード
それから Character は 0 から 127 までキャッシュされていました。 ASCII文字コードの NUL から DEL ですね。
Boolean は定数 TRUE と FALSE のどちらかを返すようになっています。
最後に Float と Double ですが、どちらもキャッシュせず常にインスタンス化するようになっていました。 浮動小数点数なので -128.0 から 127.0 の間にも膨大な量のインスタンスを生成し得るので、まあ、そりゃキャッシュしないか、という感じ。
まとめ
以上のように普段は意識しないような部分でキャッシュしておりパフォーマンス向上を図っていたりしています。 こういったJDKの努力に感謝しつつ、今後も意識せずにコーディングしようと思います。
東京でみんなと遊んできた
Elasticsearchハンズオンに参加したので ついでに東京まで行ってみんなと遊んできた!
せろてぃーたちとカラオケ行ったり、 がくぞさんと初めてお会いしたり、 しょぼちむぺろぺろしたり、 まーやさん・ちっひーは二日連続で遊んでくれたり、 とーますさんが集合時間を一時間勘違いしてたり、 まめぴーが3000万円の車を買おうとしていたり、 高校時代の友人が(私がRTするせいで)こざけさんのファンになっていたり、 楽しい休日を過ごさせてもらった!!!
あと、グラニースミスのアップルパイはあいかわらず最高だった。 東京に行ったら必ず食べたい一品。
みんなありがとう〜
楽しかった!!!