4

I am confused regarding whether memory allocation in java occurs at run time or compile time.

For example:

class Test{
  int a;
  public Test(){
    a=10;
  }
};

// somewhere else
Test t = new Test();

Is a allocated at run time or at compile time? If at compile time, how is it possible as java runs on a VM which directly takes compiled .class files?

Also:

  • when is a assigned the value 10?

  • how does it work for reference variable t?

Thanks.

didierc
  • 14,572
  • 3
  • 32
  • 52
user1649415
  • 1,085
  • 4
  • 12
  • 24
  • This example does not compile (the assignment should be merged with the declaration). – Sergey Kalinichenko Sep 05 '12 at 16:02
  • 1
    You may be confused with memory allocation sizes that can be determined at compile time versus memeory allocations that are unknown until runtime. – Jesus Ramos Sep 05 '12 at 16:02
  • The size of a reference is not known until the program runs. A 64-bit JVM can use either 32-bit or 64-bit references. – Peter Lawrey Sep 05 '12 at 16:08
  • Yes probably may I know what is the difference between the two.Any example shall greatly help.And how does determining size at compile time help coz JVM allocates memory and file is compiled somewhere else. – user1649415 Sep 05 '12 at 16:31

4 Answers4

9

Compile time no memory allocation happens. Only at load and runtime.

Compile time generates .class files that's it.

Remember you need to have a main class to run the program. When you run your program using Java with classpath to .class file, there will be steps like loading & linking etc.,

Classloaders loads the files to permgen.

When main method invoked, there will be stack created and local variables will be placed there

When runtime encounters new it creates object on heap and allocates required memory there like memory required for Test.

kosa
  • 65,990
  • 13
  • 130
  • 167
  • `a` is a primitive not an object or a reference. – Peter Lawrey Sep 05 '12 at 16:09
  • The question is confusing. ;) – Peter Lawrey Sep 05 '12 at 16:10
  • @PeterLawrey: I think OP was really looking for how the parts weave together, from loading to runtime etc., example question is, just to understand how memory JVM handles the instructions (even thought it is not perfect). I had similar confusion while learning java, as months progress got clarity. – kosa Sep 05 '12 at 16:12
5

Local variables and method parameters such as primitives or reference, are notionally allocated a place on the stack at compile time.

At runtime, this isn't guaranteed to to reflect how it is laid out in memory.

Allocation of objects on the heap only occurs at runtime.

how is it possible as java runs on VM which directly takes compile .class file.

Only the VM knows how the code will be compiled so it not possible to do memory allocation at compile time.

when is a assigned value 10

At the line where the assignment occurs. Given its not used, the JIT can discard it so it might no happen at all.

Also the same question stands for reference variable t.

t is assigned where the = is after the object is constructed.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • @peter-lawry Could you please clarify what you mean by: "Local variables and method parameters such as primitives or reference, are notionally allocated a place on the stack at compile time." 1. What do you mean by 'notionally'? 2. Why would the JVM have a stack at compile time if it isn't actually running anything? That sentence seems to contradict this sentence: "Only the VM knows how the code will be compiled so it not possible to do memory allocation at compile time." ... I'm relatively new to Java, so thank you! – Sam Malayek Jun 29 '18 at 03:07
  • @LXXIII By "notionally" I mean the byte code is for a virtual machine which doesn't really exist. So while it allocates for VM registers, how and whether they are actual registers is determined at runtime. – Peter Lawrey Jun 29 '18 at 08:28
  • @LXXIII The apparent contraction is that the `javac` compiler can allocate/assign constants, instructions, registers, stack usage but at runtime the JIT can re-optimise it to the actual hardware however it can. i.e. at runtime the machine code can look completely different. – Peter Lawrey Jun 29 '18 at 08:30
  • When you say compile time do you mean when byte code is generated or when the byte code is turned into something the CPU can run? – Anthony Nov 07 '18 at 19:22
1

Well, this one is a bit of a doozy and I'm not sure that you're going to get the exact answer that you want out of this entire thread, since really, what you're asking, is a major discourse in the internals of the compiler, and most people really don't care.

For the most part, the Java Compiler uses automatic memory management, so it's really up to the compiler to determine what it will or will not do, and this can change between versions.

But before I start explaining this, I want to clarity my notation:

  1. I will use [Object] when referring to a Java object that is not a primitive.
  2. I will use [object] when referring to a location in memory that has a value and an identifier.
  3. I will use [primitive] to refer to an [object] that is composed of one of the primitive types in Java (int, double, float, and so on, excluding string)
  4. String is a special case in java, and although it is an object, it may be treated differently than other objects.

    An [object] has a special property. It has a value and an identifier, and the process by which an identifier is resolved to a value and at which time it occurs depends on the type of binding.

    There is static binding, in which the binding can be resolved at compile time and the value or method of which is known at compile time. This is also known as "early" binding. For example.

    int a = 0; // AND //a direct function call, like print();

    There is also dynamic binding, in which the binding between an identifier and a value or a subprogram to a program cannot occur until runtime. This is also known as "late" binding. For example.

    public void foo(java.util.List list) { list.add("bar"); }

    There's also a hybrid kind of binding, but I'm not going to talk about that because I haven't discovered Java to have it.

    Now, binding is also very closely related to scoping, which is the idea that a variable "lives" in a certain scope. That's a topic of discourse I really don't want to go into (scoping is kind of a bear) and make this post a novel rather than a novella.

    The way memory allocation in Java works depends on a few things:

    1. If the reference to an [Object], [object], or [primitive] is known at compile time, and is it possible for static binding to occur, then the compiler is likely to allocate memory for those objects (notice how I didn't use brackets) at compile time.

    2. If the reference to an [Object], [object], or [primitive] cannot be known at compile time, and dynamic binding must be used, then the compiler is likely to allocate memory for those objects at runtime.

    The way that Java treats objects allocated at runtime differentiates depends on which binding was used for what type.

    1. Static binding
      • Objects that are a kind of [Object] will have their references placed on the stack at compile time, but their memory allocated on the heap at runtime. (Lazy).
      • Objects that are a kind of [primitive] will be bound and allocated at runtime.
      • Strings are a special case, but are generally handled like the case of an [Object]
    2. Late binding
      • Allocation on the stack and heap done at runtime.

    In summary, don't worry about it. It's a big headache for you to do so.

    If I'm wrong about any of this, someone please let me know. I'm a little bit rusty.

alvonellos
  • 1,009
  • 1
  • 9
  • 27
1

In java a class is not loaded until unless its object is created which are created at runtime so any member variables like "a" in yours will get space when class is loaded same goes for object it will be allocated space at run time.

Jack
  • 11
  • 1