简体   繁体   中英

Few questions about memory-allocation

I tried finding it, but I don't have suitable knowledge on terminology and can't really ask proper question on Google.

First: I am making a structure similar to Tree, where one Object has Map of children, same for child and next...

public class Attribute
{
    private String key;
    private int value;
    private HashMap<String, Attribute> modifiers;

    public Attribute(String key, int value)
    {
        this.key = key;
        this.value = value;
    }
}

The MODIFIERS is only initialized when you actually put something in it (using local void method ofc). How much memory (if it is) is used by HashMap on JUST declaration (like in code above)?

Second: Player is ofc. player object that stores all data for player.

public class Something
{
    private Player player;

    public Something() {}

    public Something(Player player)
    {
        this.player = player;
    }
}

1: Similar question, if I'd call Something(), is not-initialized PLAYER object using some memory, how much? Somewhere I read that when you declare 'something', memory is assigned based on the type of this 'something'. But how does it work with objects?

2: If I'd call Something(Player player), and since I am making a reference to object that already exist, how much memory this reference uses? (this.PLAYER = player) I am guessing that referencing like this is something like pointer, but how much memory it uses, is it constant for all objects in Java?

This is VM dependent. In most cases -- for a 32bit Oracle JVM, or a 64bit Oracle JVM 7+ instance with a heap space of less than ~32GB -- it will add 4 bytes.

Space usage is the same whether it's null or references an object (though obviously the referenced object has its own space requirements).

Here's a copy from Oracle's tech notes on JavaSE 7 JVM enhancements :

Compressed Oops

An "oop", or ordinary object pointer in Java Hotspot parlance, is a managed pointer to an object. An oop is normally the same size as a native machine pointer, which means 64 bits on an LP64 system. On an ILP32 system, maximum heap size is somewhat less than 4 gigabytes, which is insufficient for many applications. On an LP64 system, the heap used by a given program might have to be around 1.5 times larger than when it is run on an ILP32 system. This requirement is due to the expanded size of managed pointers. Memory is inexpensive, but these days bandwidth and cache are in short supply, so significantly increasing the size of the heap and only getting just over the 4 gigabyte limit is undesirable.

Managed pointers in the Java heap point to objects which are aligned on 8-byte address boundaries. Compressed oops represent managed pointers (in many but not all places in the JVM software) as 32-bit object offsets from the 64-bit Java heap base address. Because they're object offsets rather than byte offsets, they can be used to address up to four billion objects (not bytes), or a heap size of up to about 32 gigabytes. To use them, they must be scaled by a factor of 8 and added to the Java heap base address to find the object to which they refer. Object sizes using compressed oops are comparable to those in ILP32 mode.

The term decode is used to express the operation by which a 32-bit compressed oop is converted into a 64-bit native address into the managed heap. The inverse operation is referred to as encoding.

Compressed oops is supported and enabled by default in Java SE 6u23 and later. In Java SE 7, use of compressed oops is the default for 64-bit JVM processes when -Xmx isn't specified and for values of -Xmx less than 32 gigabytes. For JDK 6 before the 6u23 release, use the -XX:+UseCompressedOops flag with the java command to enable the feature.

Since your Hashmap is a Reference its memory consumption is depending on the reference size of your architecture (4 bytes on 32bit vs. 8 bytes on 64 bit)

Check out these links:

Objects take a few (should be somewhere around 32 but depends highly on the JVM version, system, ...) bytes in memory, even if you create a very much empty new Object() .

class SomeClass {
    Object someField;
}

If you add a field to that class, every instance of that object needs to have space for an extra reference to another object. A reference is roughly a memory address and should require 4 or 8 bytes. It does not matter how big the referenced object is.

class SomeClass {
    Object someField = new Object();
}

The size of an object stays the same if it actually reference another object. The value of the reference is just no longer "0", it points to some actual object.

But you obviously consume more memory because that referenced object needs to be in memory as well.

If I call new Something()

You'll get 1 Something object allocated, it's size is Basic Object + 1 x Reference. Java will never automatically create a Player object. You must tell it to do so.

If I'd call new Something(Player player)

You'll get the same thing as above, just the value stored in the reference now points to something useful. It really is just a 4 byte number field that differs in the end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM