Sunday, April 23, 2017

Evolution of the Java Memory Architecture [Java 1.7 and Java 1.8]

Java Memory Architecture [Java Memory Architecture Before Java 7]
You will have to refer to my detailed write-up on this - It explains the core concepts of the Java Memory Architecture, the ones that should get you started to understand this evolution better. The article is at : Most of the original concepts of the Java Memory Architecture are covered in detail in this article. This articles also provides information on Garbage Collection, Memory Leaks and  Most Common Memory Out of Memory Issues.

String Literals in Java are stored in String Pool. String Interning refers to a process or method by which only one copy of a specific string is stored in the memory. This is is done to allow efficient usage of memory and also of less time to retrieve, except when the string is first created. This immutable single copy of the String is called intern. Java provides a method in the String class, intern() to actually create/retrieve this copy of the string.  

Pre-Java 7 Era (String Handling)

Prior to Java 7, Interned Strings or String Literals were stored as part of PermGen Space. In the above article, the way to configure the non-expandable or fixed PermGen has been provided, along with the diagram of where exactly it is located in memory. The PermGen space is always fixed. One more point to note here is that String Interns are candidate for garbage collection just like other Objects in Java.The default string pool size is 1009 and can be set through the switch -XX:StringTableSize

Java 7 Changes (String Handling)
So, With Java 7 - Oracle Engineers decided to move String Interns to the Heap. As mentioned above, this decision has to do with the following factors:

1. Fixed/Non-Expandable Size of PermGen (Leading to Out of Memory : PermGen Space)
2. String Interns are Garbage Collected like other Objects (Based on Reference Count)  
3. Set a Higher Number of Strings - Even upto Millions of Strings maybe Possible

Java 8 Changes (String Handling)
The above Java 7 Changes of String Handling continued into Java 8. Further In Java 8, the following change was made to the memory handling related to String Interning.

1. The default number of Strings in the String Pool is now 60013 as compared to 1009

At any point in time, you can check the String Interning and Pooling usage statistics in the JVM by using -XX:+PrintStringTableStatistics (Symbol Table Statistics)

Java 8 Changes (PermGen to MetaSpace)
The most impactful change to Java/JEE has been the movement from PermGen to MetaSpace. The following are the changes in Java 8:

01. Eliminate or Reduce Out of Memory : PermGen Space  Error. (PermGen is Gone) [PermGen Elimination]
02. Memory for Class Metadata is allocated only from the Native Memory. Earlier it was from Contiguous Java Heap Memory. [MetaSpace Allocation]
03. Virtually Unlimited (or Very High) Memory for Class Metadata from Native Memory. [MetaSpace Allocation]
04. Limit the Maximum Limit for Metadata in Native Memory Using -XX:MaxMetaspaceSize [MetaSpace Configuration]
05. Garbage Collection is Triggered once the MaxMetaspaceSize is reached [MetaSpace Garbage Collection]
06. PermGen and MetaSpace are not a Direct Movement (Some Items from PermGen have been moved to MetaSpace - There are some miscellaneous items moved to the Heap Space, like Interned Strings[PermGen <> MetaSpace, Heap Space Impact]
07. The earlier PermGen flags are ignored, like -XX:PermSize and -XX:MaxPermSize. If used, a warning is issued saying that these flags are no longer valid in Java 8.  [PermGen Compiler Flags]
08. Once the MaxMetaSpaceSize is reached, Out of Memory : MetaSpace Error is thrown. [MetaSpace Error] 
09. The default MetaSpaceSize on a 32-bit and 64-bit machine is 12MB and 16MB respectively. In contrast, the default MaxPermSize was always set to 64MB. [MetaSpace Default Size]
10. The Native Memory Size can be set by -XX:MaxDirectMemorySize (The default is 128MB) [Native Memory or Direct Buffer Size]
11. MetaSpace usage  is available from the verbose GC log using -XX:+PrintGCDetails
[MetaSpace Statistics]
12. PermGen had a fixed size but MetaSpace can Auto-Tune and Auto-Increase depending on underlying OS. [MetaSpace Size Efficiency]
13. Classes can be de-allocated concurrently without GC pause. It is more efficient than in PermGen as it required frequent GC pauses. [MetaSpace Performance]

Note: Many authors have erroneously stated that PermGen is part of the Java Heap. You have to note this fact that PermGen was/is never Java Heap - It was only allocated as part of Contiguous Memory as the Java HeapIn case of Metaspace, such a Contiguous Allocation does not exist, Metaspace lies in or is allocated in the Native Memory of the Operating System.