JVM Garbage Collection

一、 Java (JVM) Memory Model - Heap

PermGen memory space has been removed in Java 8.
在这里插入图片描述

1.1 Memory Management in Java – Young Generation

The young generation is the place where all the new objects are created. When the young generation is filled, garbage collection is performed. This garbage collection is called Minor GC. Young Generation is divided into three parts – Eden Memory and two Survivor Memory spaces.

Important Points about Young Generation Spaces:

  • Most of the newly created objects are located in the Eden memory
    space.
  • When Eden space is filled with objects, Minor GC is performed and all the survivor objects are moved to one of the survivor spaces.
  • Minor GC also checks the survivor objects and move them to the other
    survivor space. So at a time, one of the survivor space is always
    empty.
  • Objects that are survived after many cycles of GC, are moved to the
    Old generation memory space. Usually, it’s done by setting a
    threshold for the age of the young generation objects before they
    become eligible to promote to Old generation.
1.2 Memory Management in Java – Old Generation

Old Generation memory contains the objects that are long-lived and survived after many rounds of Minor GC. Usually, garbage collection is performed in Old Generation memory when it’s full. Old Generation Garbage Collection is called Major GC and usually takes a longer time.

1.3 Java Heap Memory Switches
  • -Xms: For setting the initial heap size when JVM starts
  • -Xmx: For setting the maximum heap size.
  • -Xmn: For setting the size of the Young Generation, rest of the space goes for Old Generation.
  • -XX:NewRatio: Set the size of the Young Generation as a ratio of the size of the Old Generation.
  • -XX:SurvivorRatio: Set the size of Eden space relative to the size of a survivor space.
1.4 PermGen VS Metaspace

The JDK 8 HotSpot JVM is now using native memory for the representation of class metadata and is called Metaspace; similar to the Oracle JRockit and IBM JVM’s.

The good news is that it means no more java.lang.OutOfMemoryError: PermGen space problems and no need for you to tune and monitor this memory space anymore…not so fast. While this change is invisible by default, we will show you next that you will still need to worry about the class metadata memory footprint. Please also keep in mind that this new feature does not magically eliminate class and classloader memory leaks. You will need to track down these problems using a different approach and by learning the new naming convention.

PermGen space situation:

  • This memory space is completely removed.
  • The PermSize and MaxPermSize JVM arguments are ignored and a warning is issued if present at start-up.

Metaspace memory allocation model:

  • Most allocations for the class metadata are now allocated out of
    native memory.

  • The klasses that were used to describe class metadata have been
    removed.

Metaspace capacity:

  • By default class metadata allocation is limited by the amount of
    available native memory (capacity will of course depend if you use a
    32-bit JVM vs. 64-bit along with OS virtual memory availability).

  • A new flag is available (MaxMetaspaceSize), allowing you to limit the amount of native memory used for class metadata. If you don’t specify this flag, the Metaspace will dynamically re-size depending of the application demand at runtime.

Metaspace garbage collection:

  • Garbage collection of the dead classes and classloaders is triggered
    once the class metadata usage reaches the “MaxMetaspaceSize”.

  • Proper monitoring & tuning of the Metaspace will obviously be
    required in order to limit the frequency or delay of such garbage
    collections. Excessive Metaspace garbage collections may be a symptom of classes, classloaders memory leak or inadequate sizing for your application.

Java heap space impact:

  • Some miscellaneous data has been moved to the Java heap space. This means you may observe an increase of the Java heap space following a future JDK 8 upgrade.

Metaspace monitoring:

  • Metaspace usage is available from the HotSpot 1.8 verbose GC log
    output.

  • Jstat & JVisualVM have not been updated at this point based on our
    testing with b75 and the old PermGen space references are still
    present.

二、Java Garbage Collection

Java Garbage Collection is the process to identify and remove the unused objects from the memory and free space to be allocated to objects created in future processing. One of the best features of Java programming language is the automatic garbage collection, unlike other programming languages such as C where memory allocation and deallocation is a manual process.

Garbage Collector is the program running in the background that looks into all the objects in the memory and find out objects that are not referenced by any part of the program. All these unreferenced objects are deleted and space is reclaimed for allocation to other objects.

All the Garbage Collections are “Stop the World” events because all application threads are stopped until the operation completes.
Since Young generation keeps short-lived objects, Minor GC is very fast and the application doesn’t get affected by this.
However, Major GC takes a long time because it checks all the live objects. Major GC should be minimized because it will make your application unresponsive for the garbage collection duration. So if you have a responsive application and there are a lot of Major Garbage Collection happening, you will notice timeout errors.
Also, there is Full GC, which means cleaning the entire Heap – both Young and older generation spaces.
The duration taken by garbage collector depends on the strategy used for garbage collection. That’s why it’s necessary to monitor and tune the garbage collector to avoid timeouts in the highly responsive applications.

One of the basic ways of garbage collection involves three steps:

  1. Marking: This is the first step where garbage collector identifies
    which objects are in use and which ones are not in use.
  2. Normal Deletion: Garbage Collector removes the unused objects and
    reclaim the free space to be allocated to other objects.
  3. Deletion with Compacting: For better performance, after deleting
    unused objects, all the survived objects can be moved to be
    together. This will increase the performance of allocation of memory
    to newer objects.

There are two problems with a simple mark and delete approach.

  1. First one is that it’s not efficient because most of the newly
    created objects will become unused
  2. Secondly objects that are in-use for multiple garbage collection
    cycle are most likely to be in-use for future cycles too.

The above shortcomings with the simple approach is the reason that Java Garbage Collection is Generational and we have Young Generation and Old Generation spaces in the heap memory.

2.1 Garbage Collection Process

在这里插入图片描述

  1. When an object is created, it is allocated on the Eden(1) space.
    Because the Eden space is not that big, it gets full quite fast. The
    garbage collector runs on the Eden space and marks objects as alive.
  2. Once an object survives a garbage collecting process, it gets moved
    into a so-called survivor space S0(2). The second time the garbage
    collector runs on the Eden space, it moves all surviving objects
    into the S1(3) space. Also, everything that is currently on S0(2) is
    moved into the S1(3) space.
  3. If an object survives for X rounds of garbage collection (X depends
    on the JVM implementation, in my case it’s 8), it is most likely
    that it will survive forever, and it gets moved into the Old(4)
    space.

Taking everything said so far, if you look at the garbage collector graph(6), each time it has run, you can see that the objects switch to the survivor space and that the Eden space gained space. And so on and so forth. The old generation can be also garbage collected, but since it is a bigger part of the memory compared to Eden space, it does not happen that often. The Metaspace(5) is used to store the metadata about your loaded classes in the JVM.

The presented picture is actually a Java 8 application. Prior to Java 8, the structure of the memory was a bit different. The metaspace is called actually the PermGen. space. For example, in Java 6, this space also stored the memory for the string pool. Therefore, if you have too many strings in your Java 6 application, it might crash.

2.2 GC Types
TypeTargetTriggerImpact
Minor GCYoung generationEden getting fullNo effect on latency*
Major GCOld generationMinor GC failsCan have latency effect
Full GCWhole heap + MetaSpaceMinor or Major GC failCan have latency effect
2.3 GC Algorithms
TypeThreadsAlgorythmEffectDefault in
SerialYoungGen: single OldGen: singleYoungGen: mark and copy OldGen: mark sweep compactStop the world every caseJava6 if client class*
ParallelYoungGen: multi OldGen: singleYoungGen: mark and copy OldGen: mark sweep compactStop the world when OldGen cleanup is necessaryJava6 if server class**
ParalellOldYoungGen: multi OldGen: multiYoungGen: mark and copy OldGen: mark summary compactNo stop the world, but allocation is not so efficientnon default
Concurrent Mark SweepYoungGen: multi OldGen: multiYoungGen: mark and copy OldGen: mark compactNo stop the world, but allocation is not so efficientnon default
G1 GCYoungGen: multi OldGen: multimemory split into chunks and marked as usable or "under maintenance"which is cleaned by the GC currentlyBest of both, the promise ofless GC pauses, more predictable GC runsJava9
  1. Serial GC – This is the simplest garbage collector, designed for single threaded systems and small heap size. It freezes all applications while working. Can be turned on using -XX:+UseSerialGC JVM option.

  2. Parallel/Throughput GC – This is JVM’s default collector in JDK 8. As the name suggests, it uses multiple threads to scan through the heap space and perform compaction. A drawback of this collector is that it pauses the application threads while performing minor or full GC.
    It is best suited if applications that can handle such pauses, and try to optimize CPU overhead caused by the collector. It can be enabled by explicitly specifying the option: -XX:+UseParallelGC

  3. Mostly concurrent GC – If you remember, earlier in this article, it was mentioned that the garbage collecting process is actually pretty expensive, and when it runs, all thread are paused. However, we have this mostly concurrent GC type, which states that it works concurrent to the application. However, there is a reason why it is “mostly” concurrent. It does not work 100% concurrently to the application. There is a period of time for which the threads are paused. Still, the pause is kept as short as possible to achieve the best GC performance. Actually, there are 2 types of mostly concurrent GCs:

    1. Garbage First – high throughput with a reasonable application pause time. Enabled with the option: -XX:+UseG1GC

    2. Concurrent Mark Sweep – The application pause time is kept to a minimum. It can be used by specifying the option: -XX:+UseConcMarkSweepGC. As of JDK 9, this GC type is deprecated.

2.3 GC Roots

The so-called GC (Garbage Collector) roots are objects special for garbage collector. Garbage collector collects those objects that are not GC roots and are not accessible by references from GC roots.

There are several kinds of GC roots. One object can belong to more than one kind of root. The root kinds are:

Class - class loaded by system class loader. Such classes can never be unloaded. They can hold objects via static fields. Please note that classes loaded by custom class loaders are not roots, unless corresponding instances of java.lang.Class happen to be roots of other kind(s).
Thread - live thread
Stack Local - local variable or parameter of Java method
JNI Local - local variable or parameter of JNI method
JNI Global - global JNI reference
Monitor Used - objects used as a monitor for synchronization
Held by JVM - objects held from garbage collection by JVM for its purposes. Actually the list of such objects depends on JVM implementation. Possible known cases are: the system class loader, a few important exception classes which the JVM knows about, a few pre-allocated objects for exception handling, and custom class loaders when they are in the process of loading classes. Unfortunately, JVM provides absolutely no additional detail for such objects. Thus it is up to the analyst to decide to which case a certain “Held by JVM” belongs.

参考:
《Java Virtual Machine (JVM) & its Architecture》
《Java Memory Management》
《Java (JVM) Memory Model – Memory Management in Java》
《Java Garbage Collection Basics》
《Java Version Upgrades: GC Overview》
《PermGen Elimination project is promoting》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值