Caching Mechanism for Java Wrapper Types

Caching Mechanism for Java Wrapper Types

Integer caching mechanism

background

The most common interview question for Integer is to ask how the values ​​of Integer compare equal. for example:

Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true

Integer i1 = 33;
Integer i2 = new Integer(33);
System.out.println(i11 == i22);// 输出 false

Integer i1 = new Integer(33);
Integer i2 = new Integer(33);
System.out.println(i3 == i4);// 输出 false
Integer i1 = 129;
Integer i2 = 129;
System.out.println(i1 == i2);// 输出 false

Source code analysis

The first few may be easy to understand, mainly because the last one is 129, why is it still output false, this is the cache mechanism of Integer, let's look at the source code of Integer.

/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage.  The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
    
    
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
    
    
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
    
    
            try {
    
    
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
    
    
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {
    
    }
}

It can be seen from the static internal class of this cache that the cache value of Integer is from -128 to 127. Let's take a look at the bytecode file content of the compiled class file in the example just now:

// class version 52.0 (52)
// access flags 0x21
public class com/example/demoweb/controller/tt {

  // compiled from: tt.java

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 7 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/example/demoweb/controller/tt; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x9
  public static main([Ljava/lang/String;)V
    // parameter  args
   L0
    LINENUMBER 9 L0
    SIPUSH 129
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    ASTORE 1
   L1
    LINENUMBER 10 L1
    NEW java/lang/Integer
    DUP
    SIPUSH 129
    INVOKESPECIAL java/lang/Integer.<init> (I)V
    ASTORE 2
   L2
    LINENUMBER 11 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 2
    ALOAD 1
    IF_ACMPNE L3
    ICONST_1
    GOTO L4
   L3
   FRAME FULL [[Ljava/lang/String; java/lang/Integer java/lang/Integer] [java/io/PrintStream]
    ICONST_0
   L4
   FRAME FULL [[Ljava/lang/String; java/lang/Integer java/lang/Integer] [java/io/PrintStream I]
    INVOKEVIRTUAL java/io/PrintStream.println (Z)V
   L5
    LINENUMBER 14 L5
    RETURN
   L6
    LOCALVARIABLE args [Ljava/lang/String; L0 L6 0
    LOCALVARIABLE i1 Ljava/lang/Integer; L1 L6 1
    LOCALVARIABLE i2 Ljava/lang/Integer; L2 L6 2
    MAXSTACK = 3
    MAXLOCALS = 3
}

We can see Integer i1 = 129;that what the bytecode actually executes is valueOfthe method

   L0
    LINENUMBER 9 L0
    SIPUSH 129
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    ASTORE 1
   L1

Look at valueofthe source code of the method

    public static Integer valueOf(int i) {
    
    
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

Get it from the cache first, if you can’t get it from the cache, you will create a new object. The 129 here is not in the cache, so i1and i2are two different objects, so the comparison is false.

Reflection: How do Integer values ​​compare?

Let's look at the method again equals:

    public boolean equals(Object obj) {
    
    
        //先判断对象是不是int类型,是则比较的是int值,而不是比较两个对象
        if (obj instanceof Integer) {
    
    
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

Therefore, the comparison of the Integer type needs to be usedequals

Long caching mechanism

With Integerthe basis of caching, in fact, Longthe packaging type is also the same operation, let's look directly at the source code:

  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);
    }



    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);
        }
    }

LongThe cache range of the type opened from the source code is also -128-127a value between

other basic types

Byte, Short, Integer, LongThese four wrapper classes create the corresponding type of cache data with the value [-128, 127]Character by default, create the cache data with the value in the range of [0,127]Boolean , and directly return Trueor False.

Guess you like

Origin blog.csdn.net/wagnteng/article/details/132042275