Showing posts with label JVM. Show all posts
Showing posts with label JVM. Show all posts

Wednesday, 28 June 2017

Types of Java Garbage Collectors

In java, Garbage means unreferenced objects.

Garbage Collection is process of reclaiming the run-time unused memory automatically. In other words, it is a way to destroy the unused objects. Garbage collection is an automatic process in Java which relieves the programmer of object memory allocation and de-allocation chores.

Java has four types of garbage collectors:
1. Serial Garbage Collector
2. Parallel Garbage Collector
3. CMS Garbage Collector
4. G1 Garbage Collector.



Each of these four types has its own Pros and Cons. Most importantly, we can choose the type of garbage collector to be used by the JVM. This can be achieved by passing the choice as JVM argument. Each of these types differ largely and can provide completely different application performance therefore It is important to understand each of these types of garbage collectors and use it rightly based on the application.

1. Serial Garbage Collector
Serial garbage collector works by holding all the application threads. It is designed for the single-threaded environments. It uses just a single thread for garbage collection. This collector freezes all application threads whenever it’s working, which disqualifies it for all intents and purposes from being used in a server environment. It is best suited for simple command-line programs.

How to use it?
Turn on the -XX:+UseSerialGC JVM argument to use the serial garbage collector.

2. The Parallel / Throughput collector
Parallel garbage collector is also called as throughput collector. It is the default garbage collector of the JVM. Unlike serial garbage collector, its biggest advantage is that multiple threads scan to through and compact the heap. Similar to serial garbage collector this also freezes all the application threads while performing garbage collection. The downside to the parallel collector is that it will stop application threads when performing either a minor or full GC collection. The parallel collector is best suited for apps that can tolerate application pauses and are trying to optimize for lower CPU overhead caused by the collector.

The parallel garbage collector uses multiple threads to perform the young genertion garbage collection.

By default on a host with N CPUs, the parallel garbage collector uses N garbage collector threads in the collection. The number of garbage collector threads can be controlled with command-line options:
-XX:ParallelGCThreads=<desired number>

On a host with a single CPU the default garbage collector is used even if the parallel garbage collector has been requested. On a host with two CPUs the parallel garbage collector generally performs as well as the default garbage collector and a reduction in the young generation garbage collector pause times can be expected on hosts with more than two CPUs. The Parallel GC comes in two flavours.

Usage Cases
The Parallel collector is also called a throughput collector. Since it can use multiple CPUs to speed up the application throughput. This collector should be used when a lot of work need to be done and long pauses is acceptable.
For example, batch processing like printing reports or bills or performing a large number of database queries.

How to use it?
Turn on the -XX:+UseParallelGC JVM argument to use the serial garbage collector.

With this command line option you get a multi-thread young generation collector with a single-threaded old generation collector. The option also does single-threaded compaction of old generation.

Command line to start the ParallelGCDemo:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelGC -jar c:\javademos\demo\jfc\Java2D\ParallelGCDemo.jar

-XX:+UseParallelOldGC
With the -XX:+UseParallelOldGC option, the GC is both a multi threaded young generation collector and multithreaded old generation collector. It is also a multithreaded compacting collector. HotSpot does compaction only in the old generation. Young generation in HotSpot is considered a copy collector; therefore, there is no need for compaction.

Compacting describes the act of moving objects in a way that there are no holes between objects. After a garbage collection sweep, there may be holes left between live objects. Compacting moves objects so that there are no remaining holes. It is possible that a garbage collector be a non-compacting collector. Therefore, the difference between a parallel collector and a parallel compacting collector could be the latter compacts the space after a garbage collection sweep. The former would not.

Command line to start the ParallelOldGCDemo:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelOldGC -jar c:\javademos\demo\jfc\Java2D\ParallelOldGCdemo.jar

The Concurrent Mark Sweep (CMS) Collector
CMS collector (also referred to as the concurrent low pause collector) collects the tenured generation. It attempts to minimize the pauses due to garbage collection by doing most of the garbage collection work concurrently with the application threads. Normally the concurrent low pause collector does not copy or compact the live objects. A garbage collection is done without moving the live objects. If fragmentation becomes a problem, allocate a larger heap.

Note: CMS collector on young generation uses the same algorithm as that of the parallel collector.

Usage Cases
The CMS collector should be used for applications that require low pause times and can share resources with the garbage collector.
Examples: Desktop UI application that respond to events, a web-server responding to a request or a database responding to queries.

Command Line Switches
To enable the CMS Collector use:
-XX:+UseConcMarkSweepGC

To set the number of threads use:
-XX:ParallelCMSThreads=<n>

Command line example to start the ConcMarkSweepDemo:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseConcMarkSweepGC -XX:ParallelCMSThreads=2 -jar c:\javademos\demo\jfc\Java2D\ConcMarkSweepdemo.jar

The G1 Garbage Collector
The Garbage First or G1 garbage collector is available in Java 7 and is designed to be the long term replacement for the CMS collector. The G1 collector is a parallel, concurrent, and incrementally compacting low-pause garbage collector that has quite a different layout from the other garbage collectors described previously.

Command Line Switches
To enable the G1 Collector use:
-XX:+UseG1GC

Command line example to start the G1GCDemo:
java -Xmx12m -Xms3m -XX:+UseG1GC -jar c:\javademos\demo\jfc\Java2D\ G1GCDemo.jar


Thursday, 18 May 2017

What is metaspace in Java?

Until Java 7, there was an area in JVM memory called PermGen, where JVM used to keep its classes. In Java 8, Permanent Generation (PermGen) space was completely removed and is replaced by a new space called Metaspace.

The consequences of the PermGen removal is that obviously the PermSize and MaxPermSize JVM arguments are ignored and you will never get a java.lang.OutOfMemoryError: PermGen error.

Metaspace by default auto increases its size (up to what the underlying OS provides), while PermGen always has a fixed maximum size. You can set a fixed maximum for Metaspace with JVM parameters, but you cannot make PermGen auto increase.




Object generations - Java heap terminology: young, old and permanent generations?

The heap is split into several different sections, called generations.

As objects survive more garbage collections, they are promoted into different generations. The older generations are not garbage collected as often. Because these objects have already proven to be longer lived, they are less likely to be garbage collected.

1. Eden Space
2. Survivor Space
3. Tenured Generation
4. Permanent Generation, or PermGen.

When objects are first constructed, they are allocated in the Eden Space. If they survive a garbage collection, they are promoted to Survivor Space, and should they live long enough there, they are allocated to the Tenured Generation. This generation is garbage collected much less frequently.

There is also a fourth generation, called the Permanent Generationor PermGen. The objects that reside here are not eligible to be garbage collected, and usually contain an immutable state necessary for the JVM to run, such as class definitions and the String constant pool.

Note:
PermGen space is planned to be removed from Java 8 and will be replaced with a new space called Metaspace, which will be held in native memory.

Using the PermGen Space

For most applications, the PermGen area contains traditional class definitions, String constants, and not much else. Newer languages running on the JVM, such as Groovy, have the capability to create dynamic class definitions, and when used under load, this can fill up the PermGen space easily. You must be careful when creating many dynamic class definitions, and you may need to tweak the default memory allocation for PermGen space.

Thursday, 4 May 2017

Difference between 32-bit java vs. 64-bit java


Understanding 32-bit architecture in detail
As 64 > 32 then this would be an easy answer: if possible, always choose 64-bit? Wait, hold your horses. The downside of the 64-bit architecture is that the same data structures consume more memory. Our measurements show that depending on the JVM version and the operating system version along with hardware architecture you end up using 30-50% more heap than on 32-bit. Larger heap can also introduce longer GC pauses affecting application latency – running a full GC on a 4.5GB heap is definitely going to take longer than on a 3GB one. So it will not be correct to jump on the 64-bit bandwagon just because 64 is bigger than 32.

When should you ever desire to use a 64-bit JVM at all then? In most cases, the reason is large heap sizes. On different architectures, you quickly face limitations of maximum heap size on 32-bit architectures.

OS
Max
heapnotes
Linux
2GB
3GB on specific kernels, such as hugemem
Windows
1.5GB
Up to 3GB with “/3GB” boot flag and JRE compiled with /LARGEADDRESSAWARE switch)
Mac OS X
3.8GB

Reason – Address space for 32-bit system
As you may be aware of that in any 32-bit operating system, you can theoretically allocate up to 4GB of RAM. It is simply because the size of a 32-bit value will not allow any more references in memory.

2^32 = 4,294,967,296 i.e. roughly 4.29 GB

What breaks this on Windows is how process address space is handled. Windows cuts the process address space in half. One-half of it is reserved for the kernel (which a user process cannot use) and the other half for the user. It doesn’t matter how much RAM is in the box, a 32-bit process can only use 2GB of RAM. What’s even worse – this address space needs to be contiguous, so in practice, you are most often left with just 1.5-1.8GB of the heap on machines(Windows boxes).

What’s maximum amount of RAM that will be allocated to java on a 32-bit machine vs. 64-bit machine?
On the 64-bit system, theoretically, the limit is very high for any configuration available today (17.2 BILLION GB memory). Still, there are limitations imposed by vendors for various purposes, which mainly include licensing and compatibility with other native applications.

Similarly, on a 32-bit machine, the limit is 4 GB, and about only 1.5 GB is actually available for user applications for reasons stated earlier.

Trick to increase the heap space on 32-bit machine
We can pull on 32-bit windows to reduce the kernel space and grow the user space. You can use the /3GB parameter in your boot.ini. However, to actually use this opportunity, the JVM must be compiled/linked using the /LARGEADDRESSAWARE switch.

This, unfortunately, is not the case, at least with the Hotspot JVM. Until the latest JDK releases, the JVM is not compiled with this option. You are luckier if you are running on a jRockit on post-2006 versions. In this case, you can enjoy up to 2.8-2.9 GB of heap size.

How 64-bit architecture is different?
While 32 bits of information can only access 4 GB of RAM, a 64-bit machine can access 17.2 BILLION GB of system memory, at least theoretically. So it must remove all the barriers of memory consumption from your system, right? But it does not.

Windows 64-bit Home editions are still limited to 16 GB of RAM [ all because of licensing reasons], but the Professional and Ultimate versions can use up to 192 GB of RAM at present due to various compatibility issues.

The per-process limit for RAM is also greatly increased—on 64-bit Windows, instead of a 2 GB limit, each application can access up to 8 TB of virtual memory without any special configuration (besides it must be present in your system). It is a huge factor for choosing your next machine when you consider applications like video editing or virtual machines that may need to use enormous amounts of RAM.

Which versions of java you should install on 32-bit/64-bit machines?
Strictly speaking, on a 32-bit CPU architecture machine, we should install 32-bit java/JRE. On the other hand, on a 64-bit CPU architecture machine, we are free to choose between 32-bit java/JRE and 64-bit java/JRE. Both will work just fine.

In fact, on 64-bit machine decision of JRE version depends on other factors such as maximum memory needed to run our application in high load scenarios.

We should aware that high availability of memory doesn’t come for free. It does have a cost on runtime.

1) 30-50% of more heap is required on 64-bit in comparison to 32-bit. Why?
Mainly because of the memory layout in 64-bit architecture. First of all – object headers are 12 bytes on 64-bit JVM. Secondly, object references can be either 4 bytes or 8 bytes, depending on JVM flags and the size of the heap. This definitely adds some overhead compared to the 8 bytes on headers on 32-bit and 4 bytes on references.

2) Longer garbage collection pauses
Building up more heap means there is more work to be done by GC while cleaning it up from unused objects. What it means in real life is that we have to be extra cautious when building heaps larger than 12-16GB. Without fine tuning and measuring, we can easily introduce full GC pauses spanning several minutes which can result in showstoppers.

Can a class (=.class) file generated using a 32-bit java compiler be used on 64-bit java?
Yes, Java bytecode is independent of 32-bit or 64-bit systems. That’s why it is said that the compiled java code shall be executable on “any” system. Remember that just the virtual machine is compiled for special system architecture because of some native files it has in packaged bundle, and native files are never platform independent.

If so, then how 32-bit applications run on 64-bit systems? The answer is that 64-bit systems include a compatibility layer called WoW64, which actually switches the processor back and forth between 32-bit and 64-bit modes depending on which thread needs to execute; making 32-bit software run smoothly even in the 64-bit environment.

References:


What is 64-bit Java?


A 64-bit version of Java has been available to Solaris SPARC users since the 1.4.0 release of J2SE.

A 64-bit capable J2SE is an implementation of the Java SDK (and the JRE along with it) that runs in the 64-bit environment of a 64-bit OS on a 64-bit processor. You can think of this environment as being just another platform to which we've ported the SDK.
The primary advantage of running Java in a 64-bit environment is the larger address space. This allows for a much larger Java heap size and an increased maximum number of Java Threads, which is needed for certain kinds of large or long-running applications.

The primary complication in doing such a port is that the sizes of some native data types are changed. Not surprisingly the size of pointers is increased to 64 bits. On Solaris and most Unix platforms, the size of the C language long is also increased to 64 bits. Any native code in the 32-bit SDK implementation that relied on the old sizes of these data types is likely to require updating.  
Within the parts of the SDK written in Java things are simpler, since Java specifies the sizes of its primitive data types precisely. However even some Java code needs updating, such as when a Java int is used to store a value passed to it from a part of the implementation written in C.

What it is NOT?

Many Java users and developers assume that a 64-bit implementation means that many of the built-in Java types are doubled in size from 32 to 64.  This is not true.  We did not increase the size of Java integers from 32 to 64 and since Java longs were already 64 bits wide, they didn't need updating.  Array indexes, which are defined in the Java Virtual Machine Specification, are not widened from 32 to 64.  We were extremely careful during the creation of the first 64-bit Java port to insure Java binary and API compatibility so all existing 100% pure Java programs would continue running just as they do under a 32-bit VM.



Tuesday, 2 May 2017

Garbage Collection Algorithms - memory recycling


The Java virtual machine's heap stores all objects created by a running Java application. Objects are created by the new never freed explicitly by the code. Garbage collection is the process of automatically freeing objects that are no longer referenced by the program.


Why Garbage Collection?

Objects no longer needed by the program are "garbage" and can be thrown away. When an object is no longer referenced can be recycled from heap so that the space is made available new objects.

The garbage collector determines which objects are no longer referenced by the program and make available the heap space occupied by such unreferenced objects.

In the process of freeing unreferenced objects, the garbage collector must run any finalizers of objects being freed.

To freeing unreferenced objects, a garbage collector may also combat heap fragmentation. New objects are allocated, and unreferenced objects are freed such that free portions of heap memory are left in between portions occupied by live objects. New object may allocated by extending the size of the heap even though there is enough total unused space in the existing heap. If there is not enough contiguous free heap space available into which the new object will fit.

On a virtual memory system, the extra paging (or swapping) required to service an ever growing heap can degrade the performance of the executing program. On an embedded system with low memory, fragmentation could cause the virtual machine to "run out of memory" unnecessarily.

Advantages, Garbage collection relieves programmer from the burden of freeing allocated memory. It helps ensure program integrity. Garbage collection is an important part of Java's security strategy.

Disadvantage, The JVM has to keep track of which objects are being referenced by the executing program, and finalize and free unreferenced objects on the fly. This activity will likely require more CPU time than would have been required if the program explicitly freed unnecessary memory. Programmers in a garbage-collected environment have less control over the scheduling of CPU time devoted to freeing objects that are no longer needed.

Garbage Collection Algorithms

Garbage collection algorithm has two basic steps.
It must detect garbage objects.

It must reclaim the heap space used by the garbage objects and make the space available again to the program.

Garbage detection is ordinarily accomplished by defining a set of roots and determining reachability from the roots. If there is some path of references from the roots, an object is reachable (considered "live" else considered garbage because there longer use in program execution).

The root set is dependent JVM implementation, but would always include any object references in the local variables and operand stack, object references (any class variables, strings constant pool of loaded classes).

The constant pool of a loaded class may refer to strings stored on the heap, such as the class name, superclass name, super interface names, field names, field signatures, method names, and method signatures.

Two basic approaches to distinguishing live objects from garbage are reference counting and tracing.

Reference Counting Collectors

Reference counting garbage collectors distinguish live objects from garbage objects by keeping a count for each object on the heap. The count keeps track of the number of references to that object.

Reference counting was an early garbage collection strategy. In this approach, a reference count is maintained for each object on the heap. When an object is first created and a reference to it is assigned to a variable, the object's reference count is set to one. When any other variable is assigned a reference to that object, the object's count is incremented. When a reference to an object goes out of scope or is assigned a new value, the object's count is decremented.

Any object with a reference count of zero can be garbage collected. When an object is garbage collected may lead to subsequent garbage collection if any objects refers garbage collected object.

Advantage, of this approach is that a reference counting collector can run in small chunks of time closely interwoven with the execution of the program. This characteristic makes it particularly suitable for real-time environments where the program can't be interrupted for very long.

Disadvantage, is that reference counting does not detect cycles: two or more objects that refer to one another. Parent object has a reference to a child object that has a reference back to the parent. These objects will never have a reference count of zero even though they may be unreachable by the roots of the executing program.

Reference counting is the overhead of incrementing and decrementing the reference count each time.

Because of the disadvantages inherent in the reference counting approach, this technique is currently out of favor.


Tracing Collectors

Tracing garbage collectors trace out the graph of object references starting with the root nodes. Objects that are encountered during the trace are marked in some way. Marking is generally done by either setting flags in the objects themselves or by setting flags in a separate bitmap. After the trace is complete, unmarked objects are known to be unreachable and can be garbage collected.

The basic tracing algorithm is called "mark and sweep."  In the mark phase, the garbage collector traverses the tree of references and marks each object it encounters. In the sweep phase, unmarked objects are freed.
In the JVM, the sweep phase must include finalization of objects.

Compacting Collectors

Garbage collectors of JVM will likely have a strategy to combat heap fragmentation.

Mark and sweep collectors are commonly uses two strategies compacting and copying.

Both of these approaches move objects on the fly to reduce heap fragmentation. Compacting collectors slide live objects over free memory space toward one end of the heap result to other end of the heap becomes one large contiguous free area. All references to the moved objects are updated to refer to the new location.

Updating references to moved objects is sometimes made simpler by adding a level of indirection to object references. Instead of referring directly to objects on the heap, object references refer to a table of object handles. The object handles refer to the actual objects on the heap. When an object is moved, only the object handle must be updated with the new location. All references to the object in the executing program will still refer to the updated handle, which did not move. While this approach simplifies the job of heap de-fragmentation, it adds a performance overhead to every object access.

Copying Collectors

Copying garbage collectors move all live objects to a new area. As the objects are moved to the new area, they are placed side by side, thus eliminating any free space that may have separated them in the old area.

Advantage, of this approach is that objects can be copied as they are discovered by the traversal from the root nodes. There are no separate mark and sweep phases. Objects are copied to the new area on the fly, and forwarding pointers are left in their old locations. The forwarding pointers allow the garbage collector to detect references to objects that have already been moved. The garbage collector can then assign the value of the forwarding pointer to the references so they point to the object's new location.

A common copying collector algorithm is called "stop and copy."

In this scheme, the heap is divided into two regions. Only one of the two regions is used at any time. Objects are allocated from one of the regions until all the space in that region has been exhausted. At that point program execution is stopped and the heap is traversed. Live objects are copied to the other region as they are encountered by the traversal. When the stop and copy procedure is finished, program execution resumes. Memory will be allocated from the new heap region until it too runs out of space. At that point the program will once again be stopped. The heap will be traversed and live objects will be copied back to the original region. The cost associated with this approach is that twice as much memory is needed for a given amount of heap space because only half of the available memory is used at any time.






Disadvantage, of simple stop and copy collectors is that all live objects must be copied at every collection.


Generational Collectors

This facet of copying algorithms can be improved:
  1. Most objects created by most programs have very short lives.
  2. Most programs create some objects that have very long lifetimes. A major source of inefficiency in simple copying collectors is that they spend much of their time copying the same long-lived objects again and again.
Generational collectors address this inefficiency by grouping objects by age and garbage collecting younger objects more often than older objects. In this approach, the heap is divided into two or more sub-heaps, each of which serves one "generation" of objects. The youngest generation is garbage collected most often. As most objects are short-lived, only a small percentage of young objects are likely to survive their first collection. Once an object has survived a few garbage collections as a member of the youngest generation, the object is promoted to the next generation: it is moved to another sub-heap. Each progressively older generation is garbage collected less often than the next younger generation. As objects "mature" (survive multiple garbage collections) in their current generation, they are moved to the next older generation.

The generational collection technique can be applied to mark and sweep algorithms as well as copying algorithms. In either case, dividing the heap into generations of objects can help improve the efficiency of the basic underlying garbage collection algorithm.


Adaptive Collectors

An adaptive algorithm the current situation on the heap and adjusts its garbage collection technique accordingly. It may tweak the parameters of a single garbage collection algorithm as the program runs. Because every garbage collection algorithms work better in some situations, while others work better in other situations. It may switch from one algorithm to another on the fly. Or it may divide the heap into sub-heaps and use different algorithms on different sub-heaps simultaneously.


With an adaptive approach, designers of JVM implementations can choose garbage collection technique and can use algorithms for which it is best suited.

Friday, 8 July 2016

Java Virtual Machine (JVM) architecture

Java Virtual Machine (JVM) architecture
Classloader:
JVM's class loader sub system performs 3 tasks
1. It loads .class file into memory.
2. It verifies byte code instructions.
3. It allots memory required for the program.
           
Run time data area:
This is the memory resource used by JVM and it is divided into 5 parts
1. Method area: Method area stores class code and method code such as runtime constant pool, field and method data, the code for methods.

2. Heap: Objects are created on heap.

3. Java stacks: Java Stack stores frames. It holds local variables and partial results, and plays a part in method invocation and return. Each thread has a private JVM stack, created at the same time as thread. A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes.

4. Program counter registers: It contains the address of the Java virtual machine instruction currently being executed by microprocessor.

5. Native method stacks: The native method stacks are places where native methods (for example, C language programs) are executed.

Execution engine:
The byte code that is assigned to the runtime data areas in the JVM via class loader is executed by the execution engine. The execution engine reads the Java Byte code in the unit of instruction. It is like a CPU executing the machine command one by one.

Execution engine contains interpreter and JIT compiler, which covert byte code into machine code. JVM uses optimization technique to decide which part to be interpreted and which part to be used with JIT compiler. The HotSpot represents the block of code executed by JIT compiler.

Native method interface:
Native method interface is a program that connects native methods libraries (C header files) with JVM for executing native methods.

Native method library:
It holds the native libraries information.
Related Posts Plugin for WordPress, Blogger...