Memory Allocation 32bit client JVM

I am trying to understand space usage by the hotspot JVM (build 1.5.0_07-b03). I'm using windows XP and so I'm using the 32 bit JVM. An int takes up 32 bits and a long takes up 64 bits. However my test program below always gives the same memory usage even when I change the Test object to store an int and not a long. Any ideas why this is?

public class TestStuff

{

public static void main(String[] args) throws Exception

{

loadTestObjects();

}

public static void loadTestObjects() throws Exception

{

int counter = 20000000;

System.out.println("Loading objects");

Test[] arr = new Test[counter];

for (int i=0; i < counter; i++)

{

arr = new Test();

arr.value = Long.MAX_VALUE;

}

System.out.println("Done");

Thread.sleep(3000);

}

static class Test

{

private long value = 0;

public long getValue()

{

return value;

}

}

}

[1019 byte] By [driving_me_nutsa] at [2007-11-26 16:41:15]
# 1
Small typo......arr = new Test();arr.value = Long.MAX_VALUE;should readarr = new Test();arr.value = Long.MAX_VALUE;
driving_me_nutsa at 2007-7-8 23:08:15 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 2

Storage of individual objects is rounded to the nearest 64-bit boundary. In hotspot every object has a two word header and the actual java fields start after that. So an object with one int is the same size as one with one long because the first one has a wasted word. Add another field and then changing between int and long should change the total size of the object.

tom

neverevera at 2007-7-8 23:08:15 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 3

Many thanks for the info, you are quite correct.

If possible can you point me to a doc that will give me some insight into this especially hotspot for 32bit and 64bit JVM.

I need to reduce the memory usage of our application. One thing we are doing is removing non-critical properties of a particular object that has many instances and storing these in an array. For example one property in our object maybe a byte primitive and we may have 1 million of these objects. If we remove the property and store it in a byte array indexed by the unique ID stored in the object we save loads of space.

Arrays don't seem to waste space like properties in objects. A byte in an object appears to take up 32bits and so there seems little advantge storing a byte in a object over an int especially when you have to keep casting it back to a byte afte doing a simple operation like add 1.

driving_me_nutsa at 2007-7-8 23:08:15 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 4
The -XX:+PrintClassHistogram option might be useful. Run your application from a command window and press ctrl-break to get a class-wise histogram of the objects in the heap. Alternatively, if you have 6.0 you can get the same information with jmap -histo <pid>.
alan.batemana at 2007-7-8 23:08:15 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 5

You didn't read what Tom (NeverNever) said: every object has 2 words of overhead and then the fields, rounded up to a 64-bit (8 byte) boundary. So if you already have a million objects, removing some fields from them won't reduce the overhead: you still have a million objects. You will find some discontinuities where removing a byte field could save you 8 bytes in each instance because of the rounding up. On the other hand, putting those fields in a million element array ties up those million bytes, even when the garbage collector has detected that the objects that have the indexes of them are unreachable. The collector will be able to reclaim the space for the objects, but not any of the byte array. You've also introduced a level of indirection from your objects to your data, which will hurt your performance. Plus, unless you are careful, allocating (and deallocating) from the byte array will become a scalability bottleneck in your application. We've gone a lot of trouble not to have allocation or collection be a scalability bottleneck. We won't even discuss which style is more amenable to future modification, changes in the size of the data set, etc.

What problem are you trying to solve by moving some fields from objects to arrays?

PeterKesslera at 2007-7-8 23:08:15 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 6

Garbage collection is not of interest to me since the million objects are continuosly in use and never garbage collected. Several fields in these objects are required by the algorithm that runs, the other fields are required for the final result. Hence I don't mind there being a slight performance hit for retrieving the additonal data once the algorithm has run.

My aim is to reduce the memory size of the loaded objects so I can run more threads that use these objects.

I've replaced some boolean values in my objects with BitSets contained in another holder object. Each object has a unique ID. This ID is used as the index into the BitSet to retrieve the relevant boolean value.

Yes this is poor code design but this isn't a typical application and raw speed and low memory usage is the highest priority. Some byte and short properties have also been removed and placed into arrays in the holder object.

From what you are saying this may not reduce my object sizes depending on what fields and how many fields I remove.

Can you confirm that you are saying that I could remove 7 byte values from an object and yet my object size will not change if my object happens to be on a 64bit boundary?

Now you have got me thinking..........

My objects are highly linked. For the algorithm to move around fast it needs to be able to hop from one object to another and so my objects store references to other objects. On the 32bit JVM object references are 32bit but on the 64bit JVM they are 64bit. To save memory on the 64bit JVM if I know my objects (database in memory if you like) do not use more then 1GB ram is there anyway of reducing the object references down from 64bit to 32bit?

I need to move to the 64bit JVM at some point since I will be running many threads that share this in memory database. Each thread creates a working set of values to store on-going results. I want to use up all 24 threads I have on the sun T1000 and so my application goes well beyond the 2GB limit of the 32bit JVM.

driving_me_nutsa at 2007-7-8 23:08:16 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 7
Apologies I also forgot my manners. Many thanks for the reply.......
driving_me_nutsa at 2007-7-8 23:08:16 > top of Java-index,Java HotSpot Virtual Machine,Specifications...