¿Cuánto espacio ocupa un objeto en Java?

¿Cuánto espacio ocupa un objeto en Java? Esta pregunta depende de la situación. Veamos primero la clase de objeto de nivel superior en Java. Solo tiene métodos y no tiene variables miembro. Es decir, puedes conocer un objeto por usando un nuevo objeto Object. ¿Cuánto espacio ocupa al menos un objeto Java? Introducimos la herramienta jol para imprimir el diseño del objeto:

Primero agregue las dependencias de pom:

        <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.14</version>
        </dependency>

Veamos primero el Objeto:

public class JolMain {
    public static void main(String[] args) {
        Object obj = new Object();
        String layout = ClassLayout.parseInstance(obj).toPrintable();
        System.out.println(layout);
    }
}

La información de salida es la siguiente:

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

No importa si no lo entiendes, pero hemos notado alguna información clave.

12 4 (pérdida debido a la siguiente alineación del objeto)

Tamaño de instancia: 16 bytes

Pérdidas de espacio: 0 bytes internos + 4 bytes externos = 4 bytes en total

Se puede ver que un objeto Object ocupa 16 bytes, de los cuales 4 bytes son contenido que no pertenece al objeto en sí y se llenan adicionalmente. En cuanto a por qué se rellena, la alineación de objetos en Java es para mejorar la eficiencia del acceso a la memoria. Según la especificación de la Máquina Virtual Java, la dirección inicial de un objeto debe ser un múltiplo de un tamaño determinado, normalmente 8 bytes o una potencia de 2 mayor. El propósito de esto es garantizar que los campos del objeto se puedan almacenar de manera naturalmente alineada para mejorar la eficiencia del acceso a la memoria. Agregamos un parámetro a los parámetros de inicio: -XX:-UseCompressedOops. Lo mismo es el código anterior. Los resultados de salida son los siguientes:

java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           00 1c d3 17 (00000000 00011100 11010011 00010111) (399711232)
     12     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

Puede ver que no hay 4 bytes adicionales llenos en este momento. Este UseCompressedOops significa si se debe activar el puntero comprimido, porque hay un puntero de tipo en el encabezado del objeto Java que apunta al tipo al que pertenece. Se activa mediante predeterminado. Este tipo El puntero ocupa 4 bytes, por lo que un objeto Objeto en realidad solo ocupa 12 bytes de forma predeterminada. Para la alineación, se llenan 4 bytes adicionales, y cuando no habilitamos la compresión del puntero, el tipo de puntero se ubica en 8 Bytes, hay No es necesario ningún relleno de alineación en este momento.

Entonces, ¿cómo garantizar que el llenado no se realice de forma predeterminada? Intentemos crear una nueva clase de Usuario:

public class User {
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public static void main(String[] args) {
        User user = new User();
        String layout = ClassLayout.parseInstance(user).toPrintable();
        System.out.println(layout);
    }
}

Veamos el resultado: sin relleno

org.example.jol.User object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           54 c3 00 20 (01010100 11000011 00000000 00100000) (536920916)
     12     4    int User.id                                   0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

Seguimos agregando un campo de tipo largo (8 bytes) en usuario:

public class User {
    private int id;
    private long age;

    public long getAge() {
        return age;
    }

    public void setAge(long age) {
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public static void main(String[] args) {
        User user = new User();
        String layout = ClassLayout.parseInstance(user).toPrintable();
        System.out.println(layout);
    }
}

Salida: sin relleno

org.example.jol.User object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           54 c3 00 20 (01010100 11000011 00000000 00100000) (536920916)
     12     4    int User.id                                   0
     16     8   long User.age                                  0
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

Continúe agregando un campo de tipo int (4 bytes):

public class User {
    private int id;
    private long age;
    private int uid;

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public long getAge() {
        return age;
    }

    public void setAge(long age) {
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public static void main(String[] args) {
        User user = new User();
        String layout = ClassLayout.parseInstance(user).toPrintable();
        System.out.println(layout);
    }
}

Salida: hay relleno

org.example.jol.User object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           54 c3 00 20 (01010100 11000011 00000000 00100000) (536920916)
     12     4    int User.id                                   0
     16     8   long User.age                                  0
     24     4    int User.uid                                  0
     28     4        (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

De esto se puede ver que el espacio ocupado por un objeto Java es múltiplo de 8 bytes, si el espacio ocupado real no cumple con esta condición, se llenará y alineará.

en conclusión:

1. Un objeto en Java ocupa al menos 16 bytes.

2. De forma predeterminada, JVM tiene habilitada la compresión de puntero. El puntero de tipo en el encabezado del objeto ocupa 4 bytes. Desactivar la compresión de puntero ocupará 8 bytes.

3. El espacio que ocupan los objetos Java es generalmente múltiplo de 8 bytes, si no se satisface se llenará automáticamente para lograr este propósito de alineación.

Supongo que te gusta

Origin blog.csdn.net/qq_17805707/article/details/132356293
Recomendado
Clasificación