I'm struggling for the right terms a little bit because I honestly don't know the correct programming language independent computer science term for what I call structured value types. What I mean is simply this:
C++:
vector<Rect> v;
for(int i = 0; i < 1000000; ++i)
v.push_back(Rect(Point(i, i), Point(i + 1, i + 1)));
Java:
List<Rect> v = new ArrayList<Rect>();
for(int i = 0; i < 1000000; ++i)
v.add(new Rect(new Point(i, i), new Point(i + 1, i + 1)));
On a 64 bit machine, the C++ vector will use 16MB of RAM whilst the Java List will use around 48MB of RAM. Also, the C++ Rects will be tight, that is located next to each other in memory and can be iterated over very cache efficiently. The Java Rects will be all over the place. Iterating over them might cause a very large number of cache misses.
[Edit] Actually, I belive the Java list will take even more space because I forgot the per object overhead for the Point objects, which is 8 bytes each (in addition to the pointers). So the Java list would take 64MB if my ad hoc calculation is right.
Yeah, I think scott_s is right, the issue is that Java just dumps pointers on the call stack to objects on the heap. And heap objects can end up all over the place in all kinds of non-optimal locations, like out of cache, or in different pages of virtual memory.
There's not really any such thing as just a block of a data allocated for however many bytes the object needs dumped on the stack...like good old C structs AFAIK.
It's one of the problems of languages that don't let you do your own memory management.
It's not a consequence of automatic memory management. Both C# and Go have automatic memory management but their memory usage would be roughly comparable to C++ in this scenario.
[Edit] Actually, I belive the Java list will take even more space because I forgot the per object overhead for the Point objects, which is 8 bytes each (in addition to the pointers). So the Java list would take 64MB if my ad hoc calculation is right.