【翻译】Integer Cache In Java(在Java中的Integer缓存机制)

返回主页

回到顶端

This Java article is to introduce and discuss about Integer Cache.

这篇Java文章将介绍和讨论整数缓存。

This is a feature introduced in Java 5 to save memory and improve the performance.

这是Java 5中引入的一个特性,用于节省内存和提高性能。

Let us first have a look at a sample code which uses Integers and showcases the Integer Cache behavior.

让我们首先来看一个使用整数并展示整数缓存行为的示例代码。

From there lets study how and why it is implemented.

从那里让我们研究如何和为什么它被实现。

Can you guess the output of the following Java program.?

你能猜出下列Java程序的输出吗?

Obviously there is some twist in it and that’s why we have this Java article.

显然,这其中有一些曲折,这就是为什么我们要写这篇Java文章。

 1 package com.javapapers.java;
 2
 3 public class JavaIntegerCache {
 4     public static void main(String... strings) {
 5
 6         Integer integer1 = 3;
 7         Integer integer2 = 3;
 8
 9         if (integer1 == integer2)
10             System.out.println("integer1 == integer2");
11         else
12             System.out.println("integer1 != integer2");
13
14         Integer integer3 = 300;
15         Integer integer4 = 300;
16
17         if (integer3 == integer4)
18             System.out.println("integer3 == integer4");
19         else
20             System.out.println("integer3 != integer4");
21
22     }
23 }

What we generally expect is to have both statements to return false.

我们通常期望的是两个语句都返回false。

Though the values are same, the compared objects should be different as they will have different references.

虽然值是相同的,但是比较的对象应该是不同的,因为它们有不同的引用。

If you are a beginner, then in Java == checks for object references and equals() checks for values.

如果您是初学者,那么在Java中==检查对象引用,而equals()检查值。

So here in this case, different objects should be having different reference and so when compared, they should return a false boolean value.

在这种情况下,不同的对象应该有不同的引用所以当比较时,它们应该返回一个假布尔值。

What is strange here is, the behavior is not same.

奇怪的是,这里的行为是不一样的。

Two similar if-conditions returns different boolean values.

两个相似的if条件返回不同的布尔值。

Now lets look at the above Java program’s output,

现在让我们看看上面的Java程序的输出,

integer1 == integer2
integer3 != integer4

Java Integer Cache Implementation(Java整数缓存实现)
In Java 5, a new feature was introduced to save the memory and improve performance for Integer type objects handlings.

在Java 5中,引入了一个新特性来节省内存并提高整数类型对象处理的性能。

Integer objects are cached internally and reused via the same referenced objects.

整数对象在内部缓存,并通过相同的引用对象重用。

This is applicable for Integer values in range between –127 to +127 (Max Integer value).

这适用于-127到+127(最大整数值)范围内的整数值。

This Integer caching works only on autoboxing.

此整数缓存仅在自动装箱上有效。

Integer objects will not be cached when they are built using the constructor.

当使用构造函数构建整数对象时,它们不会被缓存。

Automatic conversion done by Java compiler from a primitive to its corresponding Java wrapper class type is called autoboxing.

Java编译器将原语自动转换为相应的Java包装器类类型称为自动装箱。

This is equal to using the valueOf as follows,
这就等于使用下面的valueOf,

Integer a = 10; //this is autoboxing
Integer b = Integer.valueOf(10); //under the hood

So now we know where this caching should be implemented in the Java JDK source.

现在我们知道在Java JDK源代码中应该在哪里实现缓存。

Lets look at the valueOf method source from Java JDK.

让我们看看来自Java JDK的方法源代码的值。

Following is from Java JDK 1.8.0 build 25.

下面是来自Java JDK 1.8.0 build 25的代码。

 1 /**
 2 * Returns an {@code Integer} instance representing the specified
 3 * {@code int} value.  If a new {@code Integer} instance is not
 4 * required, this method should generally be used in preference to
 5 * the constructor {@link #Integer(int)}, as this method is likely
 6 * to yield significantly better space and time performance by
 7 * caching frequently requested values.
 8 * 返回一个{@code整数}实例,表示指定的{@code int}值。如果不需要新的{@code Integer}实例,则通常应优先使用此方法,而不是构造函数{@link #Integer(int)},因为通过缓存频繁请求的值,此方法可能会产生更好的空间和时间性能。
 9 *
10 * This method will always cache values in the range -128 to 127,
11 * inclusive, and may cache other values outside of this range.
12 *
13 * 此方法将始终缓存-128到127(包括)范围内的值,并且可能缓存此范围之外的其他值。
14 * @param  i an {@code int} value.
15 * @return an {@code Integer} instance representing {@code i}.
16 * 返回一个表示{@code i}的{@code Integer}实例。
17 * @since  1.5
18 */
19 public static Integer valueOf(int i) {
20     if (i >= IntegerCache.low && i <= IntegerCache.high)
21         return IntegerCache.cache[i + (-IntegerCache.low)];
22         return new Integer(i);
23 }

There is a lookup to IntegerCache.

cache before constructing a new Integer instance.

Then there is a Java class taking care of the Integer caching.

有一个对IntegerCache的查找。
在构造一个新的整数实例之前进行缓存。
然后有一个Java类负责整数缓存。

IntegerCache Class(IntegerCache类)

IntegerCache is a private static inner class of Integer class.

IntegerCache是Integer类的一个私有静态内部类。

Lets have a look at that class.

让我们看看那个类。

It is nicely documented in the JDK and gives most of the information.

它很好地记录在JDK中,并提供了大部分信息。

 1 /**
 2      * Cache to support the object identity semantics of autoboxing for values between
 3      * -128 and 127 (inclusive) as required by JLS.
 4      * 缓存以支持JLS要求的-128和127(包括)之间值的自动装箱的对象标识语义。
 5      *
 6      * The cache is initialized on first usage.  The size of the cache
 7      * may be controlled by the {@code -XX:AutoBoxCacheMax=} option.
 8      * During VM initialization, java.lang.Integer.IntegerCache.high property
 9      * may be set and saved in the private system properties in the
10      * sun.misc.VM class.
11      *缓存在第一次使用时初始化。缓存的大小可以由{@code -XX:AutoBoxCacheMax=}选项控制。在VM初始化期间,java.lang.Integer.IntegerCache.high可以在sun.misc.VM类的私有系统属性中设置和保存属性。
12      */
13
14     private static class IntegerCache {
15         static final int low = -128;
16         static final int high;
17         static final Integer cache[];
18
19         static {
20             // high value may be configured by property
21             int h = 127;
22             String integerCacheHighPropValue =
23                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
24             if (integerCacheHighPropValue != null) {
25                 try {
26                     int i = parseInt(integerCacheHighPropValue);
27                     i = Math.max(i, 127);
28                     // Maximum array size is Integer.MAX_VALUE
29                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
30                 } catch( NumberFormatException nfe) {
31                     // If the property cannot be parsed into an int, ignore it.
32                 }
33             }
34             high = h;
35
36             cache = new Integer[(high - low) + 1];
37             int j = low;
38             for(int k = 0; k < cache.length; k++)
39                 cache[k] = new Integer(j++);
40
41             // range [-128, 127] must be interned (JLS7 5.1.7)
42             assert IntegerCache.high >= 127;
43         }
44
45         private IntegerCache() {}
46     }
47 The Javadoc 

The Javadoc comment clearly states that this class is for cache and to support the autoboxing of values between 128 and 127.

The high value of 127 can be modified by using a VM argument -XX:AutoBoxCacheMax=size.

So the caching happens in the for-loop.

It just runs from the low to high and creates as many Integer instances and stores in an Integer array named cache.

As simple as that.

This caching is doing at the first usage of the Integer class.

Henceforth, these cached instances are used instead of creating a new instance (during autoboxing).

Javadoc注释明确说明该类用于缓存并支持128到127之间的值的自动装箱。

可以使用VM参数-XX:AutoBoxCacheMax=size修改127的高值。

缓存发生在for循环中。

它只是从低到高运行,并创建尽可能多的整数实例,并存储在一个名为cache的整数数组中。

就这么简单。

这种缓存是在第一次使用Integer类时进行的。

此后,将使用这些缓存的实例而不是创建新实例(在自动装箱期间)。
Actually when this feature was first introduced in Java 5, the range was fixed to –127 to +127.

Later in Java 6, the high end of the range was mapped to java.lang.Integer.IntegerCache.

high and a VM argument allowed us to set the high number.

Which has given flexibility to tune the performance according to our application use case.

What is should have been the reason behind choosing this range of numbers from –127 to 127.

This is conceived to be the widely most range of integer numbers.

The first usage of Integer in a program has to take that extra amount of time to cache the instances.

实际上,在Java 5中首次引入该特性时,范围被固定为-127到+127。

后来在Java 6中,这个范围的高端被映射到Java .lang. integer . integercache。

high和VM参数允许我们设置高值。

这为根据我们的应用程序用例调整性能提供了灵活性。

选择-127到127这个范围的原因应该是什么。

这被认为是最广泛的整数范围。

在程序中第一次使用Integer必须花费额外的时间来缓存实例。

Cache Enforcement in Java Language Specification(Java语言规范中的缓存实施)
In the Boxing Conversion section of Java Language Specification (JLS) it is stated as follows,
在Java语言规范(JLS)的装箱转换部分中,声明如下:
If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1), or the boolean literal true or false (§3.10.3), or a character literal between ‘\u0000’ and ‘\u007f’ inclusive (§3.10.4), then let a and b be the results of any two boxing conversions of p.

如果值p盒装是一个int类型的整数文字在-128年和127年之间包容(§3.10.1),或布尔文字真或假(§3.10.3),或一个字符之间的文字‘\ u0000’和‘\ u007f包容性(§3.10.4),然后让a和b p的任意两个拳击转换的结果。

It is always the case that a == b.

a == b总是这样。

A above statement ensures that the reference of objects with values between -128 and 127 should be the same.

Reasoning for this decision is also provided as below,

Ideally, boxing a primitive value would always yield an identical reference.

In practice, this may not be feasible using existing implementation techniques.

The rule above is a pragmatic compromise, requiring that certain common values always be boxed into indistinguishable objects.

The implementation may cache these, lazily or eagerly.

For other values, the rule disallows any assumptions about the identity of the boxed values on the programmer’s part.

This allows (but does not require) sharing of some or all of these references.

Notice that integer literals of type long are allowed, but not required, to be shared.

This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices.

Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.

上面的语句确保值在-128和127之间的对象的引用应该是相同的。

该决定的理由如下:
理想情况下,装箱一个原始值总是会产生一个相同的引用。

在实践中,使用现有的实现技术可能不可行。

上面的规则是一种实用的折衷,要求某些公共值总是被包装成不可分辨的对象。

实现可以惰性地或急切地缓存它们。

对于其他值,规则不允许对程序员方面的装箱值的标识进行任何假设。

这允许(但不要求)共享部分或所有这些引用。

注意,允许共享long类型的整数字面值,但不是必需的。
这确保了在大多数情况下,行为将是期望的,而不会造成不适当的性能损失,特别是在小型设备上。

例如,内存限制较少的实现可以缓存所有char和short值,以及int和long值,范围在-32K到+32K之间。

Other Cached Objects(其他缓存对象)
This caching behavior is not only applicable for Integer objects.

We have similar caching implementation for all the integer type classes.

这种缓存行为不仅适用于整数对象。

对于所有整数类型的类,我们都有类似的缓存实现。

We have ByteCache doing the caching for Byte objects.
We have ShortCache doing the caching for Short objects.
We have LongCache doing the caching for Long objects.
We have CharacterCache doing the caching for Character objects.
Byte, Short, Long has fixed range for caching, i.e. values between –127 to 127 (inclusive).

For Character, the range is from 0 to 127 (inclusive).

Range cannot be modified via argument but for Integer, it can be done.

ByteCache对Byte对象进行缓存。

我们有ShortCache来缓存短对象。

我们让LongCache对长对象进行缓存。

我们让CharacterCache为Character对象做缓存。

字节,短,长有固定的缓存范围,即值之间-127到127(包括)。

对于字符,范围从0到127(包括)。

范围不能通过参数修改,但对于整数,可以这样做。



文章翻译自:Java Integer Cache

原文地址:https://www.cnblogs.com/LinQingYang/p/12676913.html

时间: 2024-10-01 04:20:21

【翻译】Integer Cache In Java(在Java中的Integer缓存机制)的相关文章

java整型自动装箱的缓存机制

见代码验证 /** * 整型缓存机制 * 以下缓存只在 自动装箱(autobox)时有用.new 对象无用 */ public class IntegerTypeCache { public static void main(String[] args) { /** * 运行日志当大于127时,autobox的引用判断为false */ for (int i = 0; i < 200; i++) { /** * Integer Cache test * * 缓存默认-128至127,范围可能通过

面试中对Hibernate缓存机制的回答

这是面试中经常问到的一个问题,可以按照下面的思路回答,准你回答得很完美.首先说下Hibernate缓存的作用(即为什么要用缓存机制),然后再具体说说Hibernate中缓存的分类情况,最后可以举个具体的例子.Hibernate缓存的作用: Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据Hibernat

java 从mysql中的integer转成时间类型

Date nedate = new Date(); DateFormat dateformat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss"); int seconds=1481194381; long millions=new Long(seconds)*1000; nedate.setTime(millions); System.out.println(dateformat.format(nedate)); 时间转换 Date date=n

Java和.NET中的垃圾回收机制比较

相同点: 都采用了分代的机制. 都支持并发GC. 都没有采用引用计数方式,而是采用了追踪技术. .NET中,可以通过代码GC.Collect() 强制要求CLR进行垃圾回收(由于垃圾回收是异步的,CLR有一个专用的线程负责垃圾回收,因此,即使调用GC.Collect,也并不是实时的调用了Finalize,因此要保证确实调用了析构方法,可以使用语句GC.WaitForPendingFinalizers()来确保析构方法真的被运行了,参考http://cnn237111.blog.51cto.com

Java Object类中的-----------clone()克隆机制

package java_lang_object; public class User implements Cloneable { public Address address; public int age; public String name; public User(int age,String name){ this.age = age; this.name = name; this.address = new Address("广州天河"); } public  User

java缓存机制(上) map和spring注解@Cacheable

借鉴于   https://www.cnblogs.com/ms-grf/p/7249220.html 缓存的目的在于节省访问时间以及减轻大并发量访问带来资源上的消耗. 一.外存 除计算机内存和CPU缓存以外的存储器,如常见的C.D.E.F盘,还有U盘,软盘,硬盘,光盘之类.断电后仍能保存数据的完整性. 二.内存 用于与CPU沟通.计算机中所有程序的进行都是在内存中进行,CPU中所有的运算数据以及和外存之间交换的数据都存储在其中.数据断电不保存. 三.高速缓冲 一般情况下,CPU的处理数据速度非

HTML 5缓存机制:Cache Manifest配置实例

Cache Manifest是HTML 5的一种缓存机制,文章作者直接用博客当测试环境,虽然[color=#444444 !important]应用起来非常简单,但效果却出奇的好.缓存后的速度,简直是惊人的快.像Yslow显示,打开一个缓存过的页面,只要0.729秒,比不缓存的差不多快了10倍. 一.Cache Manifest基础知识 作为一个Web开发相关的人员,都不会少听到.看到Cache这个词.是的,上面也已经说了,它是一种缓存的机制.它可以通过一个.manifest文件来配置需要缓存的

java 中的 Integer

关于Integer和int的比较 1.由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同). Integer i = new Integer(100);Integer j = new Integer(100);System.out.print(i == j); //false 2.Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer

java中Integer包装类的详细讲解(java二进制操作,所有进制转换)

程序员都很懒,你懂的! 今天为大家分享的是Integer这个包装类.在现实开发中,我们往往需要操作Integer,或者各种进制的转换等等.我今天就为大家详细讲解一下Integer的使用吧.看代码: package com.herman.test; public class IntegerTest { public static void main(String[] args) { System.out.println("Integer中的常量***************************