代码之家  ›  专栏  ›  技术社区  ›  nuno

Java/Kotlin堆大小

  •  0
  • nuno  · 技术社区  · 1 年前

    我试图了解初始化时堆中对象占用内存的空间,但我找不到关于这方面的确切信息,所以我的问题是给这两个例子,每个例子有3个类,每个实例占用的大小顺序是什么? 我知道每个int占用4个字节的空间,但如果不将其声明为val或var,是否会像在类C中那样改变这一点?拥有getter方法是否也会像在类a中那样改变它?

    class A (
        val x: Int = 999,
        val y: Int get() = 999,
        var z: Int = -1
    )
    
    class B (
        val x: Int = 0,
        val y: Int = 999,
        val z: Int = -1
    )
    
    class C (
        x: Int = 999,
        y: Int = 999,
        z: Int = 999
    )
    

    在第二个例子中,有一个像在a中一样声明的函数会影响大小吗?那么在B中,只有调用的类参数呢? C呢?它既有参数和getter,也有类中的一个函数,它有自己的参数和变量?

    class A {
      fun foo() = 123456
      val nr: Int get() = 7658894
      val foo: Int get() = nr
    
      class B(val bar: Int, val foo: Int)
    
      class C(val bar: Int) {
        val nr: Int get() = bar
        fun foo() = nr
        fun oper(num: Int): Int {
          val x = num + 1
          val y = num - 1
          return x * y
        }
      }
    }
    
    1 回复  |  直到 1 年前
        1
  •  1
  •   Gattag    1 年前

    这是一个复杂的问题,有很多变量需要考虑,所以我会做一些假设

    对于标准的Hotspot JVM(版本<=22,这也将适用于未来的版本,但不会永远适用

    32位系统

    • 对象的标头占用8个字节
    • 原始字段采用标准大小
      • 字节=1
      • 短=2
      • 字符=2
      • int=4
      • 长=8
      • 浮子=4
      • 双=8
    • 引用(对象)字段占用4个字节
    • 对象大小被填充(四舍五入)到最接近的4个字节

    64位系统

    • 对象的标头占用12个字节
    • 原始字段采用标准大小
      • 看上面
    • 引用(对象)字段占用8个字节(使用压缩OOP时为4个字节,这可能适用于堆容量小于32GB的应用程序)
    • 类大小被填充(四舍五入)到最接近的4个字节

    因此,对于以下64位系统中带有压缩指针的Java类

    class Hello {
        public byte a;
        public String b;
        public int c;
    }
    

    对象大小为 12 + 1 + 4 + 4 = 21 (24 when rounded up to the nearest 8) 24字节

    Kotlin示例

    第一个代码块

    A类

    在类A中,属性x和z由字段支持,每个字段将占用4个字节。属性y没有字段支持,因为它附加了一个getter,并且在对象实例中不占用空间

    总尺寸为 (12 + 4 + 0 + 4) ceil 8 = 24

    B类

    在类B中,所有属性都由字段支持,每个属性将占用4个字节。

    总尺寸为 (12 + 4 + 4 + 4) ceil 8 = 24

    C类

    在C类中,因为 val var 没有附加到构造函数参数,即构造函数参数。方法或构造函数的参数没有持久化,并且不能占用堆中的空间。

    总尺寸为 (12 + 0 + 0 + 0) ceil 8 = 16

    第二个代码块

    Java和Kotlin中的方法在对象的每个实例堆分配中不占用额外的空间

    A类

    类A没有字段支持的属性(因为它们有getter),并且每个实例只需要16个字节

    B类

    类B有两个int字段支持的属性,每个实例需要24个字节

    C类

    类C有一个int字段支持的属性,每个实例需要16个字节