Example in c++
Employee emp=new Employee();
Now here x bytes are created to store Employee. And y bytes are required to store reference. Hence x+y bytes are required.
Now in c++ since there is no garbage collection, its programmers duty to destroy the object.
Employee emp2=emp;
Question1: Now does it create one more address space of (x+y) for emp2 ?
In Java
It just points to the object in heap.
Question2 : So does this mean if the same object is added into a ArrayList in java, lets say 100 times then the memory used is only to store the reference of the object in heap? i.e only 100*y+x amount of memory will be used?
So does this mean if the same object is added into a ArrayList in java, lets say 100 times then the memory used is only to store the reference of the object in heap? i.e only 100*y+x amount of memory will be used? - Yes. In collections only references to actual objects (which are almost always on heap) are added.
As a side note, java has 4-byte references irrespective of the architecture (32 bit / 64 bit).
There is the stack memory of function calls' local variables; a stack as function calls are nested.
This is the memory for variables. In Java a reference to an object. The object itself is stored on the heap, garbage collected. Also an array is an Object in Java. Java does not have C structs on the stack. This is a historical design decision to keep everything simple, as successor of "complex" C++.
Now in C++ you have an immediate struct or array on the stack (without new/malloc). You then need a copy constructor, that shovels the data from one space to the other (stack or heap).
The effective difference is that in C one can have a linked list where every node is fat, with the data inside.
In Java, say a LinkedList<T> every node (a heap object) will contain an additional indirection, a reference to a T data object.
The data may be shared in Java, and are possibly copied in C.
From this perspective you can do your own calculations of memory usage. I feel the need to mention that Java's good garbage collection in general is better than malloc/free of C. So Java certainly is not that bad.
Related
Since interfaces only specify methods and not instance variables, how is storage allotted to something like:
Comparable[] aux = new Comparable[20];
How much per location storage (i.e. not counting array overhead) will be allocated?
The array is only allocating enough contiguous memory for the pointers to the objects, it doesn't need to allocate memory for the actual objects itself.
We can sometimes forget, Java still uses "pointers" (aka references), it just doesn't provide the same level of access to those pointers that other languages do
Objects are reference types, therefore every Object subtypes (including Comparator and every other interface) are reference types. It means that the size of every array item is the size of an object reference. It doesn't make a difference what kind of object it is.
I serialized an object of user defined linked list class, as every node of that list get a memory location in heap, while deserializing if the memory location is already occupied for a particular node , for example
if the memory of node 2 i.e. 200 is already occupied then how the node 1 knows about it and how the list deserialize?
Or in java the memory allocation happens in some different way.
JVM is responsible of object's management in memory. After any GC is executed, objects allocated in memory can be moved, so the LinkedList doesn't actually points a fixed adress but reference
Java has no pointers, only references to objects (safe references). A reference is similar to a pointer, because it points to a variable, an object, but you cannot view or edit the address memory of this reference (unlike C for example).
Generally speaking you would not have to do any thing about about heap manually in Java.
Serialization should not effect heap unless you have some references to serialized node.
Interms to linked list two nodes don't need to know where other node is in memory.
Hope this answers you question.
We're trying to tweak some Oracle JVM garbage collection options and one developer tried to use -XX:PretenureSizeThreshold to make sure a large array of objects was put in Tenured right away. I'm pretty sure the assumption was that the array size equals or exceeds the total size of all the objects in it.
But in Java, aren't arrays of objects just arrays of references? I.e. each object in the array, as well as the array object itself, is separate in memory and treated as separate by the garbage collector? I think the array object can still get fairly large if there are millions of entries, but it shouldn't be anywhere near the total size of the objects it "contains" if each object is much bigger than a reference.
I think there's confusion because AFAIK, in C:
It's possible to have an array of structs that really does store the structs.
It's also possible to have an array of pointers to structs.
I'm pretty sure Java always uses 1. for arrays of primitive types and always uses 2. for arrays of objects, while C can use either for any type...?
What if I use an ArrayList with frequent append()s (as we are in the case at hand)? Is only the array copied, and not the objects in the array? Also, when the array is copied, even if the old array was in Tenured the new one starts in Eden, right?
But in Java, aren't arrays of objects just arrays of references?
Just references. All objects are allocated on the heap, never in arrays or on the stack (at least officially, the optimizer may use stack allocation if possible, but this is transparent).
it shouldn't be anywhere near the total size of the objects it "contains" if each object is much bigger than a reference.
Yes, in Java whenever you say "assign/store an object", you mean the reference (pointer in C terminology).
What if I use an ArrayList with frequent append()s (as we are in the case at hand)? Is only the array copied, and not the objects in the array?
The array gets only copied when resizing is needed, i.e., very rarely and the amortized cost is proportional to the number of inserts. The referenced objects gets never copied.
Also, when the array is copied, even if the old array was in Tenured the new one starts in Eden, right?
Yes!
Using -XX:PretenureSizeThreshold for tuning is unlikely to help you.
This parameter applies only to direct Eden allocation, while most allocation is happening in TLAB (Thread Local Allocation Buffer) and -XX:PretenureSizeThreshold is ignored.
TLAB could be quite large for thread actively allocating memory (few megabytes).
You can tweak TLAB sizing, to reduce this effect, but that would probably do more harm than good.
But in Java, aren't arrays of objects just arrays of references? I.e.
each object in the array, as well as the array object itself, is
separate in memory and treated as separate by the garbage collector?
Yes.
I think there's confusion because AFAIK, in C:
It's possible to have an array of structs that really does store the structs.
It's also possible to have an array of pointers to structs.
I'm pretty sure Java always uses 1. for arrays of primitive types and
always uses 2. for arrays of objects, while C can use either for any
type...?
Java, like C, typically stores arrays of primitive types as actual arrays with elements of those types. So an int[] array with 10 elements is typically going to reserve 10×4 bytes for the array, plus overhead for the entire array object.
Arrays of objects, however, are as you say, arrays of references. So an object[] of 10 elements is going to typically take up 10×4 bytes (or perhaps 10×8 bytes on 64-bit CPUs) for the array, plus overhead, plus space for each object that each non-null element references. This corresponds in C to an array of pointers.
(I use the term "typically", because even though that's how most JVMs do it, they are not required to allocate memory in any particular fashion.)
Also be aware that Java does not have true multi-dimensional arrays like C (or C#). An int[][] in Java is actually a one-dimensional array, where each element is a reference to its own int[] subarray. In C, an int[][] really is a two-dimensional array of integers (where the lengths of all but the first dimension must be known at compile time).
Addendum
Also note that, like you say, C can have true arrays of structs, which are neither primitive types nor pointers. Java does not have this capability.
I want to improve my knowledge about memory model of programming languages (particulary in Java), so I have one question.
Here is very simple code:
// Allocating memory in heap for SimpleObject's instance
// Creating reference to this object with name so1
SimpleObject so1 = new SimpleObject();
// Allocating memory in heap for array of 10 references to SimpleObject's objects
// Now I know, that array stores only references to the objects
// (Previously I thought that array stores objects)
// Then we create reference to this array with name soArray
SimpleObject[] soArray = new SimpleObject[10];
Now the question:
// What is going on here?
soArray[0] = so1;
// object so1 had been really moved to memory area of soArray?
// And so1 reference have been updated to new memory address?
// Or we just had assigned so1 object's reference to soArray[0] element?
// Or so1 object had been copied to the soArray[0]?
// Then original so1 object has been deleted and all links to it had been updated?
If you know, how it works in other languages, such as (C, C++, C# or other), please answer, I will be glad to know it.
Everybody know, that ArrayList can be faster than LinkedList, because elements of array could be stored in CPU cache, while if we working with LinkedList, CPU has to get next object from RAM each time.
So how could it work, if at first I had created object in heap and only then I had put object in array?
UPD: Thank you guys, now I understand how array is working, but what about caching array in CPU cache in that way?
Arrays store references to objects, not the objects themselves. You therefore swap the reference at position 0 when assigning soArray[0]. The objects themselved can be moved within the heap, but this is usually due to GC, not assignments.
If the objects themselves were stored directly in the array, you could not have instances of subclasses with more instance fields in your array. They would not fit into the allocated space and therefore only become instances of the base class. This is what actually happens in C++ when you assign class instances stored on the stack.
In Java, arrays store references to objects. In C++ parlance they store pointers to objects.
SimpleObject[] soArray = new SimpleObject[10]; //Java
SimpleObject* cppArray[10]; // C++ equivalent
soArray[0] = so1; puts a reference to so1 in soArray[0] in the same way that cppArray[0] = &so1 stores a pointer to so1. The original object remains unchanged, no additional memory is allocated or deallocated.
In C++ you can store the objects directly in an array.
SimpleObject soArray[10]; // An array that stores Simple Objects in place
SimpleObject so1; // A new object
soArray[0] = so1; // This *copies* so1 into soArray[0]
We assign the reference to the object pointed by so1 to the array element.
Here's an example in using Python Tutor (there's no equivalent tool for Java that I know, but the memory model is similar, except for the Class being an object, so ignore that):
Programing languages like C,C++ will not store array values in Heap rather it keeps the value in STACK. But in Java why there is a necessity to keep array values in heap?
In Java, arrays (just like all other objects) are passed around by reference: When you pass an array to a method, it will get a reference pointing to the same location in memory, no copy is being made. This means that the array needs to remain "alive" after the method that created it, and so cannot be stored in the stack frame for the method. It needs to managed by the garbage collector, just like all other objects.
There is some research going in to optimize JVM memory allocation using "escape analysis": If an object (such as an array) can be guaranteed to never leave the current scope, it becomes possible to in fact allocate it on the stack, which is more efficient.
A short answer is that an array in Java is a reference type, and reference types live on the heap. It's worth noting that in C#, one can switch to unsafe mode and initialise arrays with stackalloc which will create the array on the stack. It's therefore quite probable that the VM would allow you to make an array on the stack, and it's merely an implementation detail that means arrays all live on the heap.
int[]a={10,20,30};
this array stores on stack, but the following array stores in heap:
`int[]num=new int num[2];`//here we build the object of array , object always located in heap
always treat arrays like java object, so do not be confused by the fact that arrays don't store on ram when we have a declaration like the one above.