关于IntegerCache.cache的介绍
目录
1、int 和 Integer区别
1.1、int 的大小
1.2、Integer大小
1.3、内存大小
2、Integer a=127 与Integer b=127
2.1、比较
2.1. 使用 == 比较
2.2. 使用 equals() 比较
2.3. 如果换成 128 呢?
2.2、原因
1. 自动装箱机制
2. 缓存机制
2.3、总结
3、存放区域
3.1. JVM 内存区域划分
1.虚拟机栈(Stack)
2.方法区(Metaspace)
3.堆内存(Heap)
3.2、IntegerCache.cache
1. 静态变量
2. 自动装箱的流程
3.3、关键点总结
4、扩展知识
4.1、缓存目的
4.2、BigInteger
前言
在处理内存,性能提升,初始化Interger数据类型的时候,合理利用IntegerCache.cache缓存和BigInteger类型来处理超大整数 时的 精度丢失 和 溢出 问题。
1、int
和 Integer
区别
如下图所示:
1.1、int
的大小
int
是 Java 的基本数据类型,固定占用 4 字节(32 位)。
- 范围:
- 最小值:
-2^31 = -2,147,483,648
- 最大值:
2^31 - 1 = 2,147,483,647
- 最小值:
1.2、Integer
大小
Integer
是int
的包装类,属于 对象类型,它的大小 不固定,取决于 JVM 实现和运行环境。
之前在介绍java内存对象布局,可参考:Java对象的内存布局及GC回收年龄的研究-CSDN博客
总大小:12(对象头) + 4(int) + 0~4(对齐) = 16 字节(典型值)
示例:
Integer a = 100; // 占用约 16 字节(堆内存)
1.3、内存大小
Integer
是对象,包含 对象头(用于 JVM 管理)、类型指针(指向类元数据)、字段(int value)。
int
是基本类型,直接存储值,没有额外开销。
2、Integer a=127
与Integer b=127
2.1、比较
2.1. 使用 ==
比较
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true
2.2. 使用 equals()
比较
System.out.println(a.equals(b)); // true
2.3. 如果换成 128
呢?
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true
2.2、原因
1. 自动装箱机制
当你写 Integer a = 127;
,Java 会自动将基本类型 int
转换为 Integer
对象。这个过程会调用 Integer.valueOf(int i)
方法。
2. 缓存机制
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}
- 默认缓存范围:
-128
到127
(可以通过-XX:AutoBoxCacheMax=
修改上限)。 - 缓存实现:
IntegerCache.cache
是一个静态数组,在类加载时初始化。
2.3、总结
- 127 在缓存范围内:
a
和b
都指向IntegerCache.cache[127]
,因此a == b
为true
。 - 128 超出缓存范围:
a
和b
会分别创建两个新对象,因此a == b
为false
。
3、存放区域
3.1. JVM 内存区域划分
a
和b
是引用变量:存放在 虚拟机栈。IntegerCache.cache
是静态数组:存放在 方法区(Metaspace)。- 堆内存:仅存放超出缓存范围的
Integer
对象。
1.虚拟机栈(Stack)
+-------------------+
| a -> 方法区的 cache[127] |
| b -> 方法区的 cache[127] |
+-------------------+
2.方法区(Metaspace)
+-------------------+
| IntegerCache.cache[127] (静态数组元素) |
+-------------------+
3.堆内存(Heap)
+-------------------+
| 仅存放超出缓存范围的 Integer 对象(如 128) |
+-------------------+
3.2、IntegerCache.cache
1. 静态变量
IntegerCache
是Integer
类的 静态内部类,其cache
数组是 静态变量。- 根据 JVM 规范:
- 静态变量 存放在 方法区的静态变量区(在 Java 8 及以后,方法区默认使用 Metaspace)。
- 对象实例 存放在 堆内存。
2. 自动装箱的流程
Integer a = 127; // 自动调用 Integer.valueOf(127)
Integer.valueOf(int i)
会检查i
是否在缓存范围内(-128 ~ 127
)。- 如果在范围内,返回 方法区中的
cache[i + offset]
。 - 如果超出范围,会在 堆内存 中创建新对象。
3.3、关键点总结
示例代码验证:
// 127 在缓存范围内
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true(a 和 b 指向方法区的同一个对象)// 128 超出缓存范围
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false(c 和 d 指向堆中的不同对象)
小结
小结
4、扩展知识
4.1、缓存目的
-
性能优化:
小范围整数使用频繁,缓存可以避免重复创建对象,减少 GC 压力。 -
节省内存:
-128
到127
有 256 个值,缓存后只需 256 个对象,而不是每次新建。 -
一致性:
在缓存范围内,==
和equals()
行为一致,方便代码逻辑判断。
4.2、BigInteger
是 Java 提供的一个 任意精度的整数类,用于处理超出
int
或long
范围的整数运算。它解决了 Java 基本数据类型(如int
、long
)在处理 超大整数 时的 精度丢失 和 溢出 问题。
-
性能开销
BigInteger
的运算速度比基本类型慢,适合 必须高精度 的场景(如密码学)。 -
不可变性
每次运算都会生成新对象,频繁操作可能导致内存浪费。如果需要频繁修改,可以使用BigDecimal
(支持浮点数)。 -
线程安全
由于不可变性,类似于String,BigInteger
是线程安全的,无需额外同步。 -
初始化方式
BigInteger a = new BigInteger("12345678901234567890");
应用场景: