Question

If I want to allocate a struct in C,

#include<stdio.h>

typedef struct container {
    int i;
} Container;

int main() {
    Container *ptr_to_container;

    ptr_to_container = (Container *) malloc(sizeof(Container));

    ptr_to_container->i = 10;

    printf("Container value: %d\n", ptr_to_container->i);

    free(ptr_one);

    return 0;
}

I explicitly have to call malloc and free. How does a VM go about doing this?

If I create an object in Java,

public class Container {
    public int i;

    public static void main(String[] args) {
        Container container = new Container();
        container.i = 10;
        System.out.println("Container value: " + container.i);
    }
}

Garbage Collectors account for the freeing, but not the allocating. How does the JVM allocate the amount of data needed? Does it call malloc or another memory management implementation?

How does the JVM know the amount of data needed? Does it add up the length of all the fields?

Was it helpful?

Solution

How does the JVM allocate the amount of data needed?

A virtual machine may use malloc, but it likely is a lower level system call.

However, they typically allocate huge blocks and carve individual objects out of those themselves rather than using 1 malloc or 1 system call per required object. The details of how a large chunk of memory are carved out into usable objects can be quite complicated, and is very specific to the implementation of the given virtual machine, and in particular to the garbage collector of that implementation. It may vary based on many factors such as the processor it's running on, etc..

The garbage collector is intimately involved in both allocations and freeing memory; it has to be involved in allocation order to do an efficient job of freeing. Often allocating memory can be as simple as advancing a pointer thru one of those huge blocks that is free.

You might read some texts by Jones: Garbage Collection: Algorithms for Automatic Dynamic Memory Management, or the newer The Garbage Collection Handbook: The Art of Automatic Memory Management

How does the JVM know the amount of data needed? Does it add up the length of all the fields?

A virtual machine knows what amount to allocate for a given class the same way that C/C++ compiler knows how to do sizeof for a given struct or class. Yes, to a degree, you could say the virtual machine adds up the fields; however, more specifically, it is responsible for positioning or laying out the fields within the object (just like in C/C++) so the virtual machine knows both the offset of each field as well as the size of the whole object. Both virtual machines and C/C++ will position fields with alignment and padding as needed for varied sizes of the fields and based on cpu alignment considerations as well.

OTHER TIPS

@ErikEidt has answered this well for the general question of VMs as a whole. This answer describes more detail specifically for the Oracle (HotSpot) JVM.

The JVM doesn't use malloc or any similar preexisting allocator. Instead, it uses low level operating system functions (eg VirtualAlloc on Windows) to allocate a single large contiguous block of address (the size of which is change by the -Xmx command line parameter) to which physical memory will be allocated as and when it is needed (see thomasrutter's answer to this question for more details).

It then uses its own internal routines to slice that up as and when needed. Particularly, allocations are performed in a section of the address space that is reserved for newly-allocated objects, so that in order to allocate the space all the JVM has to do is take the value of a pointer, and add the size of the new allocation to it. This makes allocating objects in the JVM extremely fast. Objects that aren't collected by the garbage collector quickly are then moved out of this space into more traditionally managed permanent space later (but most objects don't last long enough for this to happen to them).

In order to determine the size of the allocation, the JVM calculates the size by adding up the sizes of the fields (or references to the fields if they are objects) and adding various overhead for things that are used by the VM itself (temporary storage for the garbage collector, virtual method table, etc). This calculation is performed once for each classes when it is loaded, and (at least if the typical method of using new to create the object is used) the size is stored directly in the native code for creating the objects when it is compiled to native coded. Objects created via reflection may be entirely different, I'm not sure.

Licensed under: CC-BY-SA with attribution
scroll top