Does the compiler allocate 4 bytes of memory when the variable is declared:
int a;
Or does it allocate memory when a value is assigned to it:
a = 5;
When is memory allocated? During variable declaration or initialization?
The variable is allocated when the structure containing it is allocated.
For a local variable in a method this is (with some caveats) when the method is invoked.
For a static variable this is when the class is "initialized" (which happens some time after it's loaded and before it's first used).
For an instance variable this is when the instance is created.
In most programming languages the compiler is allowed to choose when to allocate space for variables. The only thing you are guaranteed, is that the storage will be available if and when you need it.
A short anecdote...
The C programming language used to require that all variables used in a method be declared at the top of the method. This was because compilers used to reserve storage for all stack (local) variables in a method as soon as you entered the method. Today that requirement doesn't exist in part because compilers are a lot smarter.
Most compilers of C-like languages will defer allocation of instances until first use for optimized code. The REALLY tricky thing here is that the first use may not be where you think it is, and it may not occur at all. For example, if you have the following code:
int foo(int x) {
int y = 5;
if (x > 5)
y += x;
return y;
}
You might think the first use is when you assign 5 to y, but the compiler could optimize that code to something more like:
int foo(int x) {
if (x > 5)
return 5 + x;
return 5;
}
In this code y never really exists at all.
TL;DR - The compiler actually isn't guaranteed to allocate memory on declaration or use. Trust the compiler, it is (usually) smarter than us all.
When we have “declared'' a variable, we have meant that we have told the compiler about the variable; i.e. its type and its name, as well as allocated a memory cell for the variable (either locally or globally). This latter action of the compiler, allocation of storage, is more properly called the definition of the variable.
Simply Definition = Variable Declaration + Variable initialization
JVM divides memory into stack and heap memory. Whenever we declare new variables and objects, call new method, declare a String or perform similar operations, JVM designates memory to these operations from either Stack Memory or Heap Space.
Local variables are created in the stack
Instance variables are created in the heap & are part of the object they belong to.
Reference variables are created in the stack.
Related
I am wondering when is Java creating variables during runtime (when a function is called). Please see the examples below and answer whether those are one the same.
void function someFunction(boolean test) {
if (!test) {
return;
}
int[] myVar = new int[1000000];
...
}
void function someFunction(boolean test) {
int[] myVar = new int[1000000];
if (!test) {
return;
}
...
}
I wouldn't like so spend time allocating memory only for it to be deallocated moments later, so I need to know whether Java will allocate memory needed for a certain variable (or array) needed by a function at the very beginning of that function, regardless of where the declaration happened, or will it allocate memory when it reaches the point of declaration.
EDIT:
I'm terribly sorry for confusion I'm causing. When I say variable I mean object.
Probably at the point of method entry. It is a common compiler optimization to allocate a stack frame large enough to contain all locals. If that's so, it's pretty much a single subtraction to allocate space for them all. But you'd have to examine the bytecode to be sure.
However, in this:
int[] myVar = new int[1000000];
the 'variable' is a single reference, taking up 4 or 8 bytes. The object to which the variable refers is allocated at the point the initialization is encountered in execution, by the execution of the 'new' operator.
I suspect you need to read up on the distinction between variables and objects.
In general, the Java compiler is a bit dumb in its compilation since it leaves the optimization up to the runtime JVM. As such, the compilation is mostly a straightforward translation of source code into bytecode.
https://godbolt.org/z/5xT3KchrW
In this case with the OpenJDK 17.0.0 compiler, the allocation of the array is done roughly at the same point in the bytecode as where the source code indicates.
However, the local variable of the pointer to the array is "allocated" at the time the method is called via registers. While the JVM uses a stack frame in a way very similar to C/C++, on Android's Dalvik they instead use registers to hold local variables so it isn't ever actually "allocated" at all in memory (a design decision due to the focus on ARM -- with it's plentiful registers -- rather than x86 -- which is infamous for its lack of registers.
I'm considering about how Java and C manage variable in a scope.
In java, every iterator, I create a new object and then print it. The result say that each iterator I have a new Object.
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
while (true) {
Ideone object = new Ideone();
System.out.println(object);
}
}
}
And variable of scope in C. I do the same as I do in Java. Every iterator I create a variable and print its address. But the result make me confusing because it's returning the same address, because I think every iterator it create a new variable at a random address
#include <stdio.h>
int main() {
while (1) {
int variable;
printf("%p\n", &variable);
}
}
Can anyone tell me what's under the hood of Java and C ?? And why C do not create a random address for it's variable ?
EDIT 1:
I have another question about dynamic memory management in C like this:
#include <stdio.h>
int main() {
while (1) {
int *variable = malloc(sizeof(int));
printf("%p\n", variable);
}
}
In this case, they print different address after each iterator. And each address is more then the previous the constant size.
But if free the memory like this, now it print the same address
#include <stdio.h>
int main() {
while (1) {
int *variable = malloc(sizeof(int));
printf("%p\n", variable);
realloc(variable, 0);
}
}
Is C memory management do not generate random address for new variable ?
In Java, the new Ideone() objects lifetime is not bound to a scope, you could return it from a function.
In your C code, int variable; creates an object that is automatically destroyed when you reach the end of the scope it was defined in.
Many implementations of C use a stack to allocate such objects. A stack will always give you the same address when used this way.
This comparision is a bit like apple vs. oranges. Comparing Java's new to C's malloc would show a similar behavior.
You're comparing apples to kumquats here - you're printing out the value of object (which is the address of something explicitly created on the heap each time through the loop) vs. the address of variable (which is an auto object that's typically allocated from the runtime stack).
variable has auto storage duration, meaning that storage for it is only guaranteed to be allocated over the lifetime of its enclosing scope (i.e., the body of the loop). However, as a matter of practice, most C compilers will allocate space for all auto variables in a function at function entry, even if the scope of those variables is limited to a smaller block within the function. IOW, the space for variable is allocated once, so its address doesn't change from iteration to iteration. And, given how most C implementations manage auto objects, it would be allocated from the same address anyway if it were allocated and deallocated with each loop iteration.
A more direct comparison would be looking at the address of the object variable itself, not its value, but I'm not sure how you would obtain that information (been a long time since I've done any Java).
In your Java code, you explicitly create a new object with every run in the loop. Thus, it is very likely that the different objects yield different memory addresses.
In you C-code, in contrast, you do not "create" anything, because variables are actually not "created". They are concepts of the programming language, and the compiler may decide when, where, and how often it reserves memory for the variable to hold a value. In practice, local variables are placed on the stack once at the beginning of a function or a loop, so it seems as if it were "created" only once, but this is actually something you cannot rely on.
Note, however, that the situation becomes a different one if you allocate "objects" in C as well. This would be rather comparable then to what Java does (in Java, all class-based types are handled through a pointer, but this isn't exposed to the user):
#include <stdio.h>
int main() {
while (1) {
int *variable = malloc(sizeof(int));
printf("%p\n", variable);
}
}
Besides memory leaks and running out of memory, this will print different memory addresses with each iteration.
Java use virtuel machine JVM. The garbage collection delete the variables when it's not needed any more.
In C the variables are stored in the stack or heap which you need you use malloc to allocate memory and free to deallocate.
Your output shows the address of variable in hexadecimal where in memory it's located and it's compilers decision in which memory address it should be stored.
local variables are put on the stack since in your code you did not used malloc to allocate memory on the heapit will give you the same address because stack is Last-in-first-out and your loop PUSH and POP in the same address, but if you close your terminal and run it again it will give you different address.
Close terminal and reopen run again it gives different address.
In Java, does it cost memory to declare a class level instance variable without initializing it?
For example: Does int i; use any memory if I don't initialize it with i = 5;?
Details:
I have a huge super-class that many different (not different enough to have their own super classes) sub-classes extend. Some sub-classes don't use every single primitive declared by the super-class. Can I simply keep such primitives as uninitialized and only initialize them in necessary sub-classes to save memory?
All members defined in your classes have default values, even if you don't initialize them explicitly, so they do use memory.
For example, every int will be initialized by default to 0, and will occupy 4 bytes.
For class members :
int i;
is the same as :
int i = 0;
Here's what the JLS says about instance variables :
If a class T has a field a that is an instance variable, then a new instance variable a is created and initialized to a default value (§4.12.5) as part of each newly created object of class T or of any class that is a subclass of T (§8.1.4). The instance variable effectively ceases to exist when the object of which it is a field is no longer referenced, after any necessary finalization of the object (§12.6) has been completed.
Yes, memory allocates though you are not assigning any value to it.
int i;
That takes 32 bit memory (allocation). No matter you are using it or not.
Some sub-classes don't use every single primitive declared by the super-Class. Can I simply keep such primitives as uninitialized and only initialize them in necessary sub-classes to save memory?
Again, no matter where you initialized, the memory allocates.
Only thing you need to take care is, just find the unused primitives and remove them.
Edit:
Adding one more point that unlike primitive's references by default value is null, which carries a a memory of
4 bytes(32-bit)
8 bytes on (64-bit)
The original question talks about class level variables and the answer is that they do use space, but it's interesting to look at method scoped ones too.
Let's take a small example:
public class MemTest {
public void doSomething() {
long i = 0; // Line 3
if(System.currentTimeMillis() > 0) {
i = System.currentTimeMillis();
System.out.println(i);
}
System.out.println(i);
}
}
If we look at the bytecode generated:
L0
LINENUMBER 3 L0
LCONST_0
LSTORE 1
Ok, as expected we assign a value at line 3 in the code, now if we change line 3 to (and remove the second println due to a compiler error):
long i; // Line 3
... and check the bytecode then nothing is generated for line 3. So, the answer is that no memory is used at this point. In fact, the LSTORE occurs only on line 5 when we assign to the variable. So, declaring an unassigned method variable does not use any memory and, in fact, doesn't generate any bytecode. It's equivalent to making the declaration where you first assign to it.
Yes. In your class level variables will assign to its default value even if you don't initialize them.
In this case you int variables will assign to 0 and will occupied 4 bytes per each.
Neither the Java Language Specification nor the Java Virtual Machine Specification specifies the answer to this because it's an implementation detail. In fact, JVMS §2.7 specifically says:
Representation of Objects
The Java Virtual Machine does not mandate any particular internal structure for objects.
In theory, a conformant virtual machine could implement objects which have a lot of fields using set of bit flags to mark which fields have been set to non-default values. Initially no fields would be allocated, the flag bits would be all 0, and the object would be small. When a field is first set, the corresponding flag bit would be set to 1 and the object would be resized to make space for it. [The garbage collector already provides the necessary machinery for momentarily pausing running code in order to relocate live objects around the heap, which would be necessary for resizing them.]
In practice, this is not a good idea because even if it saves memory it is complicated and slow. Access to fields would require temporarily locking the object to prevent corruption due to multithreading; then reading the current flag bits; and if the field exists then counting the set bits to calculate the current offset of the wanted field relative to the base of the object; then reading the field; and finally unlocking the object.
So, no general-purpose Java virtual machine does anything like this. Some objects with an exorbitant number of fields might benefit from it, but even they couldn't rely on it, because they might need to run on the common virtual machines which don't do that.
A flat layout which allocates space for all fields when an object is first instantiated is simple and fast, so that is the standard. Programmers assume that objects are allocated that way and thus design their programs accordingly to best take advantage of it. Likewise, virtual machine designers optimize to make that usage fast.
Ultimately the flat layout of fields is a convention, not a rule, although you can rely on it anyway.
In Java, when you declare a class attribute such as String str;, you are declaring a reference to an object, but it is not pointing yet to any object unless you affect a value to it str=value;. But as you may guess, the reference, even without pointing to a memory place, consumes itself some memory.
let have an example.
public class test {
public static void main(String args[]) {
int a=5,b=4;
int c=a+b;
int d=9;
System.out.println("ANSWER PLEASE..");
}
}
Now when we execute this code what os does?
It first create a variable named a and alocates a memory address similar things for b and c.
now what happen to d. os creates a new memory address or it just reffer to the address of c as the value is same.
First of all, the compiler doesn't do much. It basically translates it into class-files / bytecode. In the bytecode there is a number called "max locals" which tells how many local variables are required to run the method.
The JVM on the other hand, which reads this information and runs the code makes sure memory is allocated on the stack frame to fit the required variables. How much it asks for is highly implementation dependent, and it may very well optimize the whole thing, and allocate fewer bytes than what's indicated by the code.
what happen to d. os creates a new memory address or it just reffer to the address of c as the value is same.
This is tagged Java. So let's keep the OS out of it. Everything happens in memory managed by the JVM, which is allocated in big chunks in advance.
You are talking about primitive data types. Those are easy, as they are stored by value, not as references to objects living elsewhere.
You are talking about local variables. Those are allocated on the running thread's call stack (not in heap memory). Since they are primitive here, too, this does not involve the heap at all.
In your case, there is memory allocated (on the stack), for the four integers. Each of them contains the value assigned to it, not a reference. Even if the same value is assigned to all of them, they exist separately. The memory is "freed" (not really freed, but no longer used by the thread) when the method returns.
If those were not integers, but Objects, you could "share pointers" (to objects on the heap), but integers are stored by value (four bytes each).
I just know that the non-primitives (the objects) go on the heap, and methods go on the stack, but what about the primitive variables?
--update
Based on the answers, I could say the heap can have a new stack and heap for a given object? Given that the object will have primitive and reference variables..?
Primitives defined locally would be on the stack. However if a primitive were defined as part of an instance of an object, that primitive would be on the heap.
public class Test {
private static class HeapClass {
public int y; // When an instance of HeapClass is allocated, this will be on the heap.
}
public static void main(String[] args) {
int x=1; // This is on the stack.
}
}
With regards to the update:
Objects do not have their own stack. In my example, int y would actually be part of each instance of HeapClass. Whenever an instance of HeapClass is allocated (e.g. new Test.HeapClass()), all member variables of HeapClass are added to the heap. Thus, since instances of HeapClass are being allocated on the heap, int y would be on the heap as part of an instance of HeapClass.
However, all primitive variables declared in the body of any method would be on the stack.
As you can see in the above example, int x is on the stack because it is declared in a method body--not as a member of a class.
All local variables (including method arguments) go on the stack; objects and all their fields are stored in the heap. Variables are always primitives or references to objects.
Java implementations may actually store objects on the heap in such a way that it still complies with the specification. Similarly local variables may be stored in registers or become indistinct through optimisation.
primitives can be found in both places.
class Foo
{
public int x;
public static void Main()
{
int y = 3; // y is on the stack
Foo f = new Foo(); // f.x is probably on the heap
}
}
except you shouldn't really care unless you're building a JVM. A really clever optimizer might decide that since the Foo that f points to never escapes Main, and is never passed to another function that it is safe to allocate it on the stack.
With regards to the update:
The stack and the heap aren't distinguished by what is stored in them, but rather the operations provided for them. The stack allows you to allocate a piece of memory in a LIFO fashion, you can't deallocate a piece until all the pieces younger than it have also been deallocated. This conveniently aligns with how a call stack is used. You can put anything on the stack as long as it is ok for that thing to go away when your function returns. This is an optimization, as it is very quick to allocate and deallocate from a stack since it only supports being used in this manner. One could store all the local variables for a function on the heap in an implementation if one wanted to. The heap is more flexible, and consequently more expensive to use. It would not be accurate to say that an object has a stack and a heap, as I said, what distinguishes the stack from the heap is not what is in it, but the available operations.
Primitive values are allocated on the stack unless they are fields of an object, in which case they go on the heap. The stack is used for evaluation and execution, so no it doesn't make sense to say that objects with primitive fields have a stack—it is still considered to be part of the heap. Even Stack objects are allocated on the heap.