Object Header Size in Java on 64Bit Vm with <4Gb Ram

How much memory does the biggest possible array need?

Each Object has two headers, with XX:+UseCompressedOops (which is on by default), the two headers will have 12 bytes. Plus 4 bytes to keep the length of the array. Plus some eventual padding that you need to take into account also.

You can use JOL to find out how big it is. An experiment like this:

    Object[] array = new Object[100];
for(int i=0;i<100;++i){
array[i] = new Object();
}

System.out.println(GraphLayout.parseInstance(array).totalSize());

shows that it has 1600 bytes. If I change that size to 1000, I will get 16000 bytes.

But that math, you can say that the size of Object[2147483646] is going to be around 34 GB.


Notice that there is a big difference between populating that array and not. If it is not populated:

Object[] array = new Object[Integer.MAX_VALUE - 2];
System.out.println(ClassLayout.parseInstance(array).instanceSize());

It will weight arund 8GB

What actually memory overhead is in java?


What is memory overhead??

When more memory is used than the fields you created.

is it the padding?

Some is padding which can appear anywhere in the object, except the header which is always at the start. The header is typically 8-12 bytes long.

What is JVM with compressed pointers?

A technique for using 32-bit pointers in a 64-bit JVM to save memory.

is it reference??

References can use this technique but so can pointers to the class information for an object.

If 32-bit JVM is used then overhead will be less?

Possibly, though this is the same as using compressed pointers for references and classes.

But is it because of padding?

It's because 64-bit pointers use more space than 32-bit pointer.

So is it better to use always 32-bit JVM for memory efficiency or for performance?

No, the 32-bit processor model has 32-bit registers where as the 64-bit model has twice as many registers which are double the sized (64-bit) means far more can be held in the fastest memory, the registers. 64-bit calculations tend to be faster as well with a 64-bit processing model.

In general I would recommend you always use the 64-bit JVM unless you a) can't or b) have a very small amount of memory.

In this image at starting itself they shown as 16 bytes JVM overhead,why that so??

This is not strictly correct. This assumes you have a non compressed class reference so the header is 12-bytes, however objects are 8 byte aligned by default, which means there will be 4 bytes of padding at the end (which totals 16 bytes but it's not all at the start)

FAQ: Why can 32-bit Compressed OOP address more than 4 GB

Object have to be 8-byte aligned by default. This makes memory management easier but wastes some padding sometimes. A side effect is that the address of every object will have 000 for the lowest three bits (it has to be a multiple of 8) Those bits don't need to be stored. This allows a compressed oops to address 8 * 4 GB or 32 GB.

With a 16 byte object alignment the JVM can address 64 GB with 32-bit reference (however the padding overhead is higher and might not be worth it)

IFAQ: Why is it slower at around 28 - 32 GB

While the reference can be multiplied by 8, the heap doesn't start at the start of memory. It typically start around 4 GB after. This means that if you want the full 32 GB you have to add this offset, which has a slight overhead.

Heap sizes:

  • < 4 GB - zero extend address
  • 4 - 28 GB - multiply by 8 or << 3 note: x64 has an instruction for this to support double[] and long[]
  • 28 - 32 GB - multiple by 8 and add a register holding the offset. Slightly slower, but not usually a problem.

How to create more than Integer.MAX_VALUE objects in a jvm?

I'm assuming you're asking in regards to this.

You don't necessarily need to create more than Integer.MAX_VALUE objects. You just need to create some until there is a collision. You can do that relatively easily.

public static void main(String[] args) throws Exception {
final int LENGTH = Integer.MAX_VALUE / 256;
Object[] values = new Object[LENGTH];
int count = 0;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
Object o = new Object();
int hashCode = o.hashCode();
if (hashCode > LENGTH)
continue;
if (values[hashCode] != null) {
System.out.println("found after " + count + ": " + values[hashCode] + " same hashcode as " + o);
System.out.println(values[hashCode] == o);
System.exit(0);
} else {
System.out.println(hashCode);
values[hashCode] = o;
count++;
}
}
}

For example, on my machine, this stops after 4712 new instances with a hashCode smaller than Integer.MAX_VALUE / 256. This means that two Object instances, which weren't eligible for GC, had the same hashCode.

The above prints

...
5522036
4166797
5613746
found after 4712: java.lang.Object@6aca04 same hashcode as java.lang.Object@6aca04
false

rails how to mapping a virtual view to a model

There are multiple ways to fulfill your requirement:

  1. In your CashOrderStatus model, you can set table name to override default ORM mapping:
class CashOrderStatus > ActiveRecord::Base
set_table_name "order_statuses"

belongs_to:cash_order
end
  1. You can implement STI(Single Table Inheritance) functionality where in your database table "order_statuses" one more column will be there: type which will hold the derived model class name(In this case, CashOrderStatus).

So your model will look like this:

class CashOrderStatus > OrderStatus
set_table_name "order_statuses"

belongs_to:cash_order
end

And OrderStaus model will be derived from AR::Base class. Try it.

NOTE: Sorry for the class inheritance notation. It should be < instead of >. There is formatting issue in my stackoverflow account, so I put like this :-)

Invalid maximum heap size

You are using 32 bit VM (Java HotSpot(TM) Client VM) which can be mapped to maximum 4G (Only 2 GB in reality) 2^32 address locations Maximum Java heap size of a 32-bit JVM on a 64-bit OS

Error message suggest you are using 5GB heap memory which is not supported on 32 bit architecture

Invalid maximum heap size: -Xmx5096m
The specified size exceeds the maximum representable size.

Could not create the Java virtual machine.

You can modify the -Xmx parameter to use anythinng <=2g should work here

Java program failing to map Native memory allocation

You are possibly impacted by this

As per the post's suggested workarounds :

There are 2 possible workaround here

  1. Disable compressed Oops (-XX:-UseCompressedOops) with slight performance penalty. This will instruct JVM to run without the
    Compressed Oops feature and it would not try to fit the Java Heap in
    the first 4GB of heap
  2. Keep the CompressedOops and set the base of the Java Heap with the JVM option -XX:HeapBaseMinAddress=n to specify the address where the
    Java Heap should start from set it to a higher address so that there
    is enough room available for the native mallocs


Related Topics



Leave a reply



Submit