Java梱包クラスキャッシュ分析

3825 ワード

Integer
Integer内部にはIntegerCacheクラスがあり、このクラスはint型の数値をキャッシュするために使用され、デフォルトのキャッシュの範囲は-128~127であり、システム属性java.lang.Integer.IntegerCache.highが設定されている場合、このシステム属性を取得し、その後、比較を行う.
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);


通常、上限は127かjava.lang.Integer.IntegerCache.highで、もしこのシステムの属性がInteger.MAX_VALUE - 128 - 1よりも大きいならば、上限はInteger.MAX_VALUE - 128 - 1です(誰がそんなに卵が痛いのは上限をこんなに高く設定しますか?).上限を決定すると、内部のキャッシュ配列が初期化されます.
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
 cache[k] = new Integer(j++);

予め-128~127の範囲内に入れておくInteger対象Integer.valueOf(int)が呼び出されると、まず、入力されたint値が-128127の範囲内であるかどうかを判断し、`ImageCache`から直接`Integer`オブジェクトを取得すると、Integerを再作成するメモリオーバーヘッドが回避される.-128127の範囲内でなければ、次のような新しいIntegerが直接生成されます.
    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

Integer内部にキャッシュがありますが、同じように箱詰め対象のDoubleLongなどのタイプでキャッシュはありますか?
Byte
    private static class ByteCache {
        private ByteCache(){}

        static final Byte cache[] = new Byte[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Byte((byte)(i - 128));
        }
    }
    
    public static Byte valueOf(byte b) {
        final int offset = 128;
        return ByteCache.cache[(int)b + offset];
    }
Byteはベースタイプbyteの箱詰めクラスであり、byteは1バイトを表し、ちょうど-128~127であるため、Byteの箱詰めクラスはbyteの可能なすべての値をキャッシュしている.
Short
  private static class ShortCache {
        private ShortCache(){}

        static final Short cache[] = new Short[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Short((short)(i - 128));
        }
    }
    
    public static Short valueOf(short s) {
        final int offset = 128;
        int sAsInt = s;
        if (sAsInt >= -128 && sAsInt <= 127) { // must cache
            return ShortCache.cache[sAsInt + offset];
        }
        return new Short(s);
    }


Shortもキャッシュされている-128~127の範囲内の値であることがわかります
Long
   private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }
    
    public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }
    
Long内部にもキャッシュが使用されており、範囲も同様-128~127
Double、Float
    public static Float valueOf(float f) {
        return new Float(f);
    }
    
    public static Double valueOf(double d) {
        return new Double(d);
    }
    
Double,Floatの内部ではキャッシュが使用されず、毎回新しいオブジェクトが直接生成されていることがわかります.
なぜこの2つのクラスはキャッシュされていないのですか?意味がないため……この2つのクラスはすべて浮動小数点数を代表して、Integer、Short、Byteの中から見ることができて、キャッシュは最大256個の数を貯蓄して、キャッシュは多すぎてかえってもっと多くのメモリを占有して、浮動小数点数は小数点の後ろの数を含んで、もし256個の数をキャッシュするならば、どのように範囲を選ぶべきですか?それとも-128~127?では、126.01はどうすればいいですか.キャッシュされていません.126.10もキャッシュされていません.だから、浮動小数点数にとってキャッシュヒット率が低すぎます.キャッシュしないほうがいいです.メモリの無駄です.