深入剖析Integer的缓存机制
2020/3/19 17:01:44
本文主要是介绍深入剖析Integer的缓存机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
上一篇,我们对Long、Short、Byte三个类的构造方法、内部Cache类以及valueOf进行了分析。
看了文章的人,肯定心中有个疑惑,怎么没有对最为常用的Integer类进行分析?
实际上,正是由于Integer最为常用,JDK源码对其内部缓存实现类IntegerCache
和valueOf
方法做了进一步的优化。
测试代码
我们首先还是来看一段测试代码。
@Test public void testInteger() { int primaryInt = 127; Integer int1 = Integer.valueOf(primaryInt); Integer int2 = 127; Assert.assertTrue(int1 == int2); int1 = new Integer(127); Assert.assertFalse(int1 == int2); primaryInt = 128; int1 = Integer.valueOf(primaryInt); int2 = 128; Assert.assertFalse(int1 == int2); // 1 int1 = new Integer(128); Assert.assertFalse(int1 == int2); } 复制代码
上述测试代码在不设置JVM参数的情况下,是可以通过测试的。
但是一旦我们在运行该测试的时候设置了JVM参数-Djava.lang.Integer.IntegerCache.high=255
,这个测试将在
注析1处失败!下图为IntelliJ IDEA中JVM参数的设置。
这又是为什么呢?
按照我们上一篇的分析,Integer类提供的缓存机制应该也是缓存[-128,127]之间的值。
在不提供-Djava.lang.Integer.IntegerCache.high=255
JVM参数的时候确实是对的。但是一旦提供了该参数,情况就发生了变化。
变化究竟是怎样的?我们且看Integer的源代码。
分析
我们打开java.lang.Integer的源代码。其中关键性代码如下。
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 = 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() {} } 复制代码
上面是Integer的内部缓存类IntegerCache
的源代码,我们发现跟Long#LongCache
的代码要复杂不少。
IntegerCache
内部还是一样使用的cache
数组作为缓存数据的机制;IntegerCache
使用了low
、high
分别作为缓存的数值的最小值和最大值;low
实际上是一个固定的值-128
;high
是可以设置的:- 通过设置变量
h=127
作为high
的默认值; - 通过
VM.getSavedProperty("java.lang.Integer.IntegerCache.high")
获取java.lang.Integer.IntegerCache.high
参数值视为变量integerCacheHighPropValue
,并将 该值转换为int
,然后取127和该转换后的int值中较大的作为变量i
的值; - 取
i
,Integer.MAX_VALUE - (-low) -1
中较小的值作为h
的值;这里之所以取中较小的值,是因为数组size最大为Integer.MAX_VALUE
。 也就是说数组元素下标最大为Integer.MAX_VALUE - 1
的。而IntegerCache
的cache
数组中需要存放128个负数,所以cache的下标需要再减128也就是-low
, 也就是Integer.MAX_VALUE - (-low) -1
。 h
再赋值给high
作为能够缓存的最大整数。
- 通过设置变量
- 计算出
high
之后的代码就是初始化cache
数组的过程。上一篇已经分析过了,这里就不再重复了。
从上述计算high
的过程中可以看出,java.lang.Integer.IntegerCache.high参数的设置必须要大于127的整数,否则该设置就是无效的。
由于缓存机制的变化,Integer.valueOf
的实现也发生一些变化,如下所示。
实际上,也就是只对IntegerCache.low
和IntegerCache.high
之间的值返回缓存。
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } 复制代码
总结
- 如果项目需要大量重复使用范围较大的Integer类型值的时候,请通过设置
java.lang.Integer.IntegerCache.high
参数来扩充缓存: - 通过命令行运行的话,可以这样设置:
java -Djava.lang.Integer.IntegerCache.high=xxx Main.class
- 通过特定开发工具运行的话,直接设置运行参数:
-Djava.lang.Integer.IntegerCache.high=xxx
java.lang.Integer.IntegerCache.high
参数的值应该是一个大于127的值,否则跟没有设置效果是一样的。
最后,这里为什么low
是一个固定值-128? 按理,我们也是需要扩充负数的缓存范围的。至今也没有一个开发人员给出合理的解析。
这篇关于深入剖析Integer的缓存机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求
- 2024-10-01使用 golang 将ETH账户的资产平均分散到其他账户
- 2024-10-01JWT用户校验课程:从入门到实践
- 2024-10-01Server Component课程入门指南