Refer to this article: https://www.baeldung.com/jvm-compressed-oops
First, let's find out what an oop is:
The HotSpot JVM uses a data structure called oops or Ordinary Object Pointers to represent objects. These oops are equivalent to native C pointers. The instanceOops are a special kind of oop that represents the object instances in Java. Moreover, the JVM also supports a handful of other oops that are kept in the OpenJDK source tree.
Furthermore

A very neat feature is the compressing of oops to 32 bits:
As it turns out, the JVM can avoid wasting memory by compressing the object pointers or oops, so we can have the best of both worlds: allowing more than 4 GB of heap space with 32-bit references in 64-bit machines!
Finally:
To enable oop compression, we can use the -XX:+UseCompressedOops tuning flag. The oop compression is the default behavior from Java 7 onwards whenever the maximum heap size is less than 32 GB. When the maximum heap size is more than 32 GB, the JVM will automatically switch off the oop compression. So memory utilization beyond a 32 Gb heap size needs to be managed differently.
So, the answer to your question is: you simply passed beyond the threshold of 32 GB as the maximum heap size.
Proof
Look at your graphs and see that the behavior we are speaking about happens at the level of 32 GB.
Answer from Lajos Arpad on Stack Overflowjava - Increasing the JVM maximum heap size for memory intensive applications - Stack Overflow
How is the default max Java heap size determined? - Stack Overflow
Java memory usage in containers
Increase heap size in Java - Stack Overflow
Videos
When you are using JVM in 32-bit mode, the maximum heap size that can be allocated is 1280 MB. So, if you want to go beyond that, you need to invoke JVM in 64-mode.
You can use following:
$ java -d64 -Xms512m -Xmx4g HelloWorld
where,
- -d64: Will enable 64-bit JVM
- -Xms512m: Will set initial heap size as 512 MB
- -Xmx4g: Will set maximum heap size as 4 GB
You can tune in -Xms and -Xmx as per you requirements (YMMV)
A very good resource on JVM performance tuning, which might want to look into: http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html
Get yourself a 64-bit JVM from Oracle.
On Windows, you can use the following command to find out the defaults on the system where your applications runs.
java -XX:+PrintFlagsFinal -version | findstr HeapSize
Look for the options MaxHeapSize (for -Xmx) and InitialHeapSize for -Xms.
On a Unix/Linux system, you can do
java -XX:+PrintFlagsFinal -version | grep HeapSize
I believe the resulting output is in bytes.
For Java SE 5: According to Garbage Collector Ergonomics [Oracle]:
initial heap size:
Larger of 1/64th of the machine's physical memory on the machine or some reasonable minimum. Before J2SE 5.0, the default initial heap size was a reasonable minimum, which varies by platform. You can override this default using the -Xms command-line option.
maximum heap size:
Smaller of 1/4th of the physical memory or 1GB. Before J2SE 5.0, the default maximum heap size was 64MB. You can override this default using the -Xmx command-line option.
UPDATE:
As pointed out by Tom Anderson in his comment, the above is for server-class machines. From Ergonomics in the 5.0 JavaTM Virtual Machine:
In the J2SE platform version 5.0 a class of machine referred to as a server-class machine has been defined as a machine with
- 2 or more physical processors
- 2 or more Gbytes of physical memory
with the exception of 32 bit platforms running a version of the Windows operating system. On all other platforms the default values are the same as the default values for version 1.4.2.
In the J2SE platform version 1.4.2 by default the following selections were made
- initial heap size of 4 Mbyte
- maximum heap size of 64 Mbyte
Ok, so my company has a product that was recently moved to the cloud from old bare metal. The core is the legacy app, the old monolith. A lot of care has been taken for that one, as such I'm not worried about it. However there are a bunch of new micro-services added around it that have had far less care.
The big piece that I'm currently worried about is memory limits. Everything runs in Kubernetes, and there are no memory limits on the micro service pods. I feel like I know this topic fairly well, but I hope that this sub will fact check me here before I start pushing for changes.
Basically, without pod memory limits, the JVM under load will keep trying to gobble up more and more of the available memory in the namespace itself. The problem is the JVM is greedy, it'll grab more memory if it thinks memory is available to keep a buffer above what is being consumed, and it won't give it up.
So without pod level limits it is possible for one app to eat up the available memory in the namespace regardless of if it consistently needs that much. This is a threat to the stability of the whole ecosystem under load.
That's my understanding. Fact check me please.
You can increase to 2GB on a 32 bit system. If you're on a 64 bit system you can go higher. No need to worry if you've chosen incorrectly, if you ask for 5g on a 32 bit system java will complain about an invalid value and quit.
As others have posted, use the cmd-line flags - e.g.
java -Xmx6g myprogram
You can get a full list (or a nearly full list, anyway) by typing java -X.
It is possible to increase heap size allocated by the JVM by using these command line options:
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
In the following example, minimum heap size is set to 16mb, and the maximum to 64mb:
java -Xms16m -Xmx64m ClassName
I was pondering it for a while now and... it would be great if JVM would allow specifying maximum (total) JVM memory usage.
Currently, we can specify it for various parts of JMV (most notably heap) but very often other parts (meta, threads, code, gc, symbols, etc) take also part of memory (often significant) thus specifying only heap can be tricky, especially if we want to maximize resource usage on the machine (be that VM or within container)...