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

Thursday, 18 May 2017

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.



Wednesday, 18 May 2016

What is a native method and necessities?

The method is implemented in "native" code. That is, code that does not run in the JVM. It's typically written in C or C++.

Regular Java class definitions are compiled to bytecode, held in class files. This bytecode is platform independent, and is translated into specific instructions for the architecture and operating system running the bytecode at run time.

Java native code necessities
1. We need to run some platform-specific code, perhaps referencing a platform specific library or making some operating system–level calls, or making some operating system–level calls.
2. Hardware access and control.
3. Use of commercial software and system services[hardware related].
4. Use of legacy software that hasn't or cannot be ported to Java.
5. Using native code to perform time-critical tasks.


A native method is well-defined header in C or C++, identifying the class name, the Java method name, as well as its parameters and return type. When your code is loaded into the JVM, you need to register your native code so that it knows exactly what needs to be run when your native method is called.

How is memory allocated?

The new keyword allocates memory on the Java heap. The heap is the main pool of memory, accessible to the whole of the application.

If there is not enough memory available to allocate for that object, the JVM attempts to reclaim some memory from the heap with a garbage collection.

If it still cannot obtain enough memory, an OutOfMemoryError is thrown, and the JVM exits.

Thursday, 3 September 2015

Stack vs. Heap Memory

Java Heap Memory

Heap memory is used by java runtime to allocate memory to Objects and JRE classes. Whenever we create any object, it’s always created in the Heap space.

Garbage Collection runs on the heap memory to free the memory used by objects that doesn’t have any reference. Any object created in the heap space has global access and can be referenced from anywhere of the application.

Java Stack Memory

Java Stack memory is used for execution of a thread. They contain method specific values that are short-lived and references to other objects in the heap that are getting referred from the method.

Stack memory is always referenced in LIFO (Last-In-First-Out) order. Whenever a method is invoked, a new block is created in the stack memory for the method to hold local primitive values and reference to other objects in the method. As soon as method ends, the block becomes unused and become available for next method.

Difference between Heap and Stack Memory

Heap memory
Stack memory
Heap memory is used by all the parts of the application.
whereas stack memory is used only by one thread of execution.

Whenever an object is created, it’s always stored in the Heap space and stack memory contains the reference to it.

Stack memory only contains local primitive variables and reference variables to objects in heap space.
Objects stored in the heap are globally accessible.

Stack memory can’t be accessed by other threads.
Heap memory is more complex because it’s used globally and  Heap memory is divided into Young-Generation, Old-Generation etc.

Memory management in stack is done in LIFO manner.
We can use -Xms and -Xmx JVM option to define the startup size and maximum size of heap memory.

We can use -Xss to define the stack memory size.
If heap memory is full, it throws java.lang.OutOfMemoryError: Java Heap Space error.

When stack memory is full, Java runtime throws java.lang.StackOverFlowError.

Because of simplicity in memory allocation (LIFO), stack memory is very fast when compared to heap memory.

Heap memory lives from the start till the end of application execution.

Stack memory is short-lived.
Stack memory size is very less when compared to Heap memory.


Related Posts Plugin for WordPress, Blogger...