标签:文本 modern different nes 没有 art daemon lte open
Part of "memory-management" series
Please follow me on Twitter for updates and let me know if something can be improved in the post.
In this multi-part series, I aim to demystify the concepts behind memory management and take a deeper look at memory management in some of the modern programming languages. I hope the series would give you some insights into what is happening under the hood of these languages in terms of memory management. In this chapter, we will look at the memory management of the Java Virtual Machine(JVM) used by languages like Java, Kotlin, Scala, Clojure, JRuby and so on.
If you haven’t read the first part of this series, please read it first as I explained the difference between the Stack and Heap memory there which would be useful to understand this chapter.
First, let us see what the memory structure of JVM is. This is based on JDK 11 onwards. Below is the memory available to a JVM process and is allocated by the Operating System(OS).
This is the native memory allocated by the OS and the amount depends on OS, processor, and JRE. Let us see what the different areas are for:
This is where JVM stores objects or dynamic data. This is the biggest block of memory area and this is where Garbage Collection(GC) takes place. The size of heap memory can be controlled using the Xms
(Initial) and Xmx
(Max) flags. The entire heap memory is not committed to the Virtual Machine(VM) as some of it is reserved as virtual space and the heap can grow to use this. Heap is further divided into “Young” and “Old” generation space.
This is the stack memory area and there is one stack memory per thread in the process. This is where thread-specific static data including method/function frames and pointers to objects are stored. The stack memory limit can be set using the Xss
flag.
This is part of the native memory and doesn’t have an upper limit by default. This is what used to be Permanent Generation(PermGen) Space in earlier versions of JVM. This space is used by the class loaders to store class definitions. If this space keeps growing, the OS might move data stored here from RAM to virtual memory which might slow down the application. To avoid that its possible to set a limit on meta-space used with the -XX:MetaspaceSize
and -XX:MaxMetaspaceSize
flag in which case application might just throw out of memory errors.
This is where the Just In Time(JIT) compiler stores compiled code blocks that are often accessed. Generally, JVM has to interpret byte code to native machine code whereas JIT-compiled code need not be interpreted as it is already in native format and is cached here.
This is where native code for any shared libraries used are stored. This is loaded only once per process by the OS.
Now that we are clear about how memory is organized let’s see how the most important parts of it are used when a program is executed.
Let’s use the below Java program, the code is not optimized for correctness hence ignore issues like unnecessary intermediatory variables, improper modifiers and such, the focus is to visualize stack and heap memory usage.
Click on the slides and move forward/backward using arrow keys to see how the above program is executed and how the stack and heap memory is used:
Note: If the slides look cut off at edges, then click on the title of the slide or here to open it directly in SpeakerDeck.
int
are stored directly on the StackEmployee
, Integer
, String
are created on the Heap and is referenced from the Stack using Stack pointers. This applies to static fields as wellThe Stack as you can see is automatically managed and is done so by the operating system rather than JVM itself. Hence we do not have to worry much about the Stack. The Heap, on the other hand, is not automatically managed by the OS and since its the biggest memory space and holds dynamic data, it could grow exponentially causing our program to run out of memory over time. It also becomes fragmented over time slowing down applications. This is where the JVM helps. It manages the Heap automatically using the garbage collection process.
Now that we know how JVM allocates memory, let us see how it automatically manages the Heap memory which is very important for the performance of an application. When a program tries to allocate more memory on the Heap than that is freely available(depending on the Xmx
config) we encounter out of memory errors.
JVM manages the heap memory by garbage collection. In simple terms, it frees the memory used by orphan objects, i.e, objects that are no longer referenced from the Stack directly or indirectly(via a reference in another object) to make space for new object creation.
The garbage collector in JVM is responsible for:
JVM garbage collectors are generational(Objects in Heap are grouped by their age and cleared at different stages). There are many different algorithms available for garbage collection but Mark & Sweep is the most commonly used one.
JVM uses a separate daemon thread that runs in the background for garbage collection and the process runs when certain conditions are met. Mark & Sweep GC generally involves two phases and sometimes there is an optional third phase depending on the algorithm used.
This type of GC is also referred to us stop-the-world GC as they introduce pause-times in the application while performing GC.
JVM offers few different algorithms to choose from when it comes to GC and there might be few more options available depending on the JDK vendor you use(Like the Shenandoah GC, available on OpenJDK). The different implementations focus on different goals like:
As of JDK 11, which is the current LTE version, the below garbage collectors are available and the default used is chosen by JVM based on hardware and OS used. We can always specify the GC to be used with the -XX
switch as well.
-XX:+UseSerialGC
switch.-XX:+UseParallelGC
switch.-XX:+UseG1GC
switch.-XX:+UseZGC
switch.Regardless of the collector used, JVM has two types of GC process depending on when and where its performed, the minor GC and major GC.
This type of GC keeps the young generation space compact and clean. This is triggered when below conditions are met:
Initially, all the areas of heap space are empty. Eden memory is the first one to be filled, followed by survivor space and finally by tenured space.
Let us look at the minor GC process:
Click on the slides and move forward/backward using arrow keys to see the process:
Note: If the slides look cut off at edges, then click on the title of the slide or here to open it directly in SpeakerDeck.
So we saw how minor GC reclaims space from the young generation. It is a stop-the-world process but it’s so fast that it is negligible most of the time.
This type of GC keeps the old generation(Tenured) space compact and clean. This is triggered when below conditions are met:
System.gc()
, or Runtime.getRunTime().gc()
from the program.MaxMetaspaceSize
option for the JVM and there is not enough space to load new classes.Let us look at the major GC process, it’s not as complex as minor GC:
This post should give you an overview of the JVM memory structure and memory management. This is not exhaustive, there are a lot more advanced concepts and tuning options available for specific use cases and you can learn about them from https://docs.oracle.com. But for most JVM(Java, Kotlin, Scala, Clojure, JRuby, Jython) developers this level of information would be sufficient and I hope it helps you write better code, considering these in mind, for more performant applications and keeping these in mind would help you to avoid the next memory leak issue you might encounter otherwise.
I hope you had fun learning about the JVM internals, stay tuned for the next post in the series.
If you like this article, please leave a like or a comment.
You can follow me on Twitter and LinkedIn.
Also published at Dev.to
附原文: https://deepu.tech/memory-management-in-jvm/
后记:由于很多网站(csdn,oschina,头条)写博文的富文本编辑器不支持iframe嵌入,故而改成超链接了。且不同的jdk版本(引入的新特性)有出入(比如我早年用jdk1.4时,很多时髦的特性都没有,都得自己想办法),所以请根据实际情况阅读该文。
我也追加几条以前的资料供参考(更多家业请看 https://github.com/dongguangming/java,后续(最近由于存储空间到了上限,需要整理)会慢慢上传):
标签:文本 modern different nes 没有 art daemon lte open
原文地址:https://www.cnblogs.com/dongguangming/p/14069722.html