The theoretical1 largest single Java object you will be able to create (if you have a large enough heap) will be a long[]
with 231 - 1 elements. That is 16GB. In theory.
But the largest object you are going to be able to create for a given heap size is platform dependent.
In practice the maximum array length is JVM specific and is slightly less than 231 - 1; see Do Java arrays have a maximum size?
The JVM's heap is segmented into two or more "spaces", and any given object must fit inside a single space1. An object that approaches the size of the entire heap is impossible because of this, and because various other heap-related overheads.
The default sizes of the various GC spaces are calculated by the memory manager, and I've never come across a simple formula that predicts what the sizes will be.
So, if you really want to know the largest object you can allocate, then your best bet is to measure it experimentally. Write a simple program that allocates successively larger arrays until you get an OOME. But note that the answer you get will depend on your VM version and on the JVM command line options you use.
Suppose, my application has only a single class and I'm creating exactly a single object.
Your BigSingleObj
class is not actually allocating a large object at all. The HashMap
will start out small2, and will automatically grow as entries are added to it.
Furthermore, the HashMap
object is actually composed of a number of objects. The largest of these will be the hash array, but the total size of the HashMap
will be 5 or more times the size of that array. And then you need to add the space occupied by the keys and values ... which in your case will depend on the string sizes.
All of this means that the size of largest allocatable object in Java is not a useful predictor of how many entries you can store in your big HashMap
.
As this answer notes, you can use the JOL tool to determine the size of an instance of a given Java type. However, it relies on measuring the size of an instance (in various ways) rather than predicting what it would be. In your example, it would give a misleading answer (see footnote 2) unless you populated the map before measuring it.
1 - It is more complicated with G1GC. It splits the old generation into many standard-sized regions that can be collected independently. If an object is more than half the size of a standard region, G1GC classes it as "humongous", and creates a "humongous region" to hold it. This may trigger a full collection to (in effect) defragment at the region level. Even so, the process of creating a humongous region may fail if the heap is already too close to full or too fragmented.
2 - Even if you supply a large capacity
argument, current versions of HashMap
will defer the allocation of the internal hash array until it is needed.