JVM内存角度剖析int和integer的区别

在运行时,intInteger 在内存上的区别主要体现在它们的存储位置和内存分配方式上。以下是详细说明:

1. 内存分配

  • int

    • 作为基本数据类型,int 直接存储在栈内存中。
    • 栈内存用于存储方法调用过程中的局部变量,存取速度快,生命周期随方法调用的结束而结束。
    • 因为 int 是直接存储数值,不涉及对象的创建和垃圾回收,所以效率较高。
  • Integer

    • 作为包装类,Integer 是对象类型,存储在堆内存中。
    • 堆内存用于存储所有的对象,生命周期由垃圾回收器管理。
    • Integer 对象包含了一个 int 类型的成员变量,用于存储实际的数值,同时还包含了对象头信息和其他元数据。

2. 内存布局

  • int

    • 在栈内存中,int 直接占用 4 字节(32 位)空间,表示实际的整数值。
  • Integer

    • 在堆内存中,一个 Integer 对象占用的空间要比一个 int 多。除了实际的 int 值外,还包括对象头和一些额外的元数据。
    • 对象头包含了用于垃圾回收和类型信息的指针,以及其他与对象有关的数据。在 HotSpot 虚拟机中,一个对象头通常占用 12 字节(在 64 位 JVM 中,没有开启指针压缩时)。
    • 实际的 int 值占用 4 字节。
    • 额外的元数据和对齐填充可能会导致 Integer 对象占用更多的内存,具体取决于 JVM 的实现。

3. 示例说明

以下是一个简单的示例,用于说明在内存中的布局:

public class Main {
    public static void main(String[] args) {
        // 使用 int
        int intValue = 10;

        // 使用 Integer
        Integer integerObject = 10;

        // 打印内存地址(伪代码,实际 Java 不提供直接获取内存地址的方法)
        System.out.println("int value memory address: " + System.identityHashCode(intValue));
        System.out.println("Integer object memory address: " + System.identityHashCode(integerObject));
    }
}

4. 内存使用示意图

  • int 在栈内存中的布局:

    |--------------------|
    |   intValue (10)    | <- 栈
    |--------------------|
    
  • Integer 在堆内存中的布局:

    栈:
    |--------------------|
    | integerObject ref  | -> 指向堆中的 Integer 对象
    |--------------------|
    
    堆:
    |--------------------|
    |   Object Header    |
    |--------------------|
    |   int value (10)   |
    |--------------------|
    

总结

  • int:直接在栈内存中分配,内存占用少,访问速度快。
  • Integer:在堆内存中分配,需要额外的内存开销来存储对象头和元数据,访问速度相对较慢,需要依赖垃圾回收机制管理生命周期。

了解这些内存上的区别,有助于在开发中根据具体需求选择合适的数据类型,以优化性能和内存使用。

整数缓存机制

在 Java 中,Integer 类通过一个内部的缓存机制来缓存一定范围内的整数对象。这个缓存范围默认是从 -128127,在这个范围内的整数会被缓存起来,重复使用,以减少对象的创建开销。

实现原理

整数缓存机制在 Integer 类的源码中实现。以下是相关代码片段:

public final class Integer extends Number implements Comparable<Integer> {
    // 缓存的最小值
    private static final int LOW = -128;
    // 缓存的最大值,默认是127,可以通过启动参数调整
    private static final int HIGH;
    // 缓存数组
    private static final Integer[] CACHE;

    static {
        // 获取最大缓存值
        int high = 127;
        String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            int parsed = Integer.parseInt(integerCacheHighPropValue);
            high = Math.max(parsed, high);
        }
        HIGH = high;

        // 初始化缓存数组
        CACHE = new Integer[(HIGH - LOW) + 1];
        int j = LOW;
        for (int k = 0; k < CACHE.length; k++) {
            CACHE[k] = new Integer(j++);
        }
    }

    // 返回缓存的 Integer 对象或创建新的 Integer 对象
    public static Integer valueOf(int i) {
        if (i >= LOW && i <= HIGH) {
            return CACHE[i + (-LOW)];
        }
        return new Integer(i);
    }
}

工作原理

  1. 缓存初始化

    • Integer 类在静态代码块中初始化了一个 Integer 对象的缓存数组,默认缓存范围是从 -128127
    • 缓存数组 CACHE 存储了这些范围内的所有 Integer 对象。
  2. 缓存获取

    • 当调用 Integer.valueOf(int i) 方法时,如果 i 的值在缓存范围内(-128127),则直接返回缓存数组中的 Integer 对象。
    • 如果 i 的值不在缓存范围内,则创建一个新的 Integer 对象并返回。

优势

  1. 减少对象创建

    • 缓存机制避免了在常用范围内频繁创建相同的 Integer 对象,减少了内存分配和垃圾回收的开销。
  2. 提高性能

    • 通过缓存,常用整数的对象复用提高了程序的运行性能,因为直接从缓存中获取对象比创建新对象要快。

示例

以下是一个简单的示例,演示了缓存机制的效果:

public class IntegerCacheTest {
    public static void main(String[] args) {
        // 在缓存范围内的整数
        Integer a = Integer.valueOf(100);
        Integer b = Integer.valueOf(100);

        // 超出缓存范围的整数
        Integer c = Integer.valueOf(200);
        Integer d = Integer.valueOf(200);

        // 比较内存地址
        System.out.println(a == b); // 输出: true
        System.out.println(c == d); // 输出: false
    }
}

在上面的示例中:

  • ab 是相同的对象,因为 100 在缓存范围内。
  • cd 是不同的对象,因为 200 超出了默认缓存范围。

自定义缓存范围

可以通过 JVM 启动参数 -XX:AutoBoxCacheMax=<size> 来调整缓存范围,例如:

java -XX:AutoBoxCacheMax=1000 IntegerCacheTest

这样可以将缓存范围扩展到 -1281000

总结:

  • Integer 类维护了一个缓存数组,用于缓存常用范围内的 Integer 对象。
  • 通过缓存机制,提高了内存使用效率和运行性能。
  • 可以通过 JVM 启动参数调整缓存范围。
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值