Source
Before we move on to the performence things, we need to learn that what is really going on in the background of JVM (Java Virtual Machine).
在开始讨论性能问题之前,我们需要了解 JVM(Java 虚拟机)的后台到底发生了什么。
This is the starting point of every developer who wants to learn and tune performance in order to gain some speed. So let’s dive into the world of codes.
这是每一个想要学习和调整性能以提高速度的开发人员的起点。因此,让我们进入代码的世界。
In Java, memory management is handled by JVM automatically to store your variables, classes, fields and beyond… The first thing we will learn is in JVM, memory splitted into two regions.
在 Java 中,内存管理由 JVM 自动处理,用于存储变量、类、字段和其他内容......我们首先要了解的是,在 JVM 中,内存分为两个区域。
One of them is called Stack and the other one is Heap.
其中一个称为堆(Stack),另一个称为堆(Heap)。
What is Stack? 什么是堆栈?
First region we are going to learn is Stack.
我们要学习的第一个区域是栈。
In JVM, stack is very efficent approach to memory management and not only just one but also every thread has its own stack region.
在 JVM 中,堆栈是一种非常有效的内存管理方法,不仅是一个线程,每个线程都有自己的堆栈区域。
In stack, instantiated fieds are added to memory one on another just like its name stacking.
在堆栈中,实例化的文件一个接一个地添加到内存中,就像堆栈的名字一样。
As you can see, this area is not big enough to store objects so what is happening is primitive types and object pointers can be stored directly instead of storing a whole object.
正如你所看到的,这个区域不够大,无法存储对象,因此可以直接存储原始类型和对象指针,而不是存储整个对象。
And when it is time to remove, first object needs to be removed first because like I said, data is stacked, we can’t reach the bottom unless we remove those items.
当需要删除时,需要先删除第一个对象,因为就像我说的,数据是堆叠在一起的,如果不删除这些项目,我们就无法到达底部。
What is Heap? 什么是堆?
Now, let’s look at the other region called Heap.
现在,让我们来看看另一个名为堆的区域。
As you can see it from the GIF, heap size is bigger than stack because heap is the main region for holding objects.
从 GIF 中可以看到,堆的大小大于栈,因为堆是存放对象的主要区域。
Every created object is held in heap and its reference is helding in stack.
每个创建的对象都存放在堆中,其引用存放在栈中。
Like figure shown below
如下图所示
public List<String> test() { String newString = "test"; List<String> testList = new ArrayList<>(); testList.add(newString); return testList; }
On the contrary, there is just one heap that application has.
相反,应用程序只有一个堆。
That sounds quite reasonable because we might have more than one big object that passes one method to another.
这听起来很合理,因为我们可能有不止一个大对象,这些对象会将一个方法传递给另一个方法。
So basically, stack is used for local variables and there could be many stacks but they all use one heap to store the objetcs.
因此,堆栈基本上是用于局部变量的,可能有很多堆栈,但它们都使用一个堆来存储对象。
Those objects pointers are held in stack so when we want to pass objects between methods, we are not copying objects like in stack, we are passing its reference.
这些对象的指针保存在堆栈中,因此当我们要在不同方法之间传递对象时,我们不是像在堆栈中那样复制对象,而是传递其引用。
Furthermore, heap is not one, solid region at all. If you zoom in to the heap, you will see 4 different areas
此外,堆根本不是一个完整的区域。如果放大堆,你会看到 4 个不同的区域
Actually those are called generations. Heap is builded on two main generations. One of them is young and the other one is old. Young generation is divided into three spaces. Eden, survivor zero and survivor one spaces. It will be more clear when you learn what they do. Created objects are first placed in eden space. Then eden is fulled, objects are moved to the survivor one or survivor zero. After, created objects are placed in eden again. When eden is full, both eden and survivor zero or one will be moved to the survivor zero or one. If objects are moved more than five, those objects are now placed in old generation. This means, now those objects are needed and will live in old generation unless it looses its pointer. If there are no variables in the stack that holds its reference, this means that object is eligible for garbage collection. Last one is so important for performance issues and thus we need to learn how Java memory works to understand it.
实际上,这就是所谓的 "代"。堆建立在两个主代上。一个是Young,另一个是Old。Young代分为三个空间。Eden、survivor0 和survivor1。
当你了解了它们的作用后就会更清楚了,新创建的对象首先被放置在Eden。
然后Eden被填满,存活对象被移动到survivor1或survivor0。处理之后,后续创建的对象会再次放置在Eden中。
如果移动的对象超过 5 次,这些对象就会被放置在Old中。
这意味着,现在这些对象都是需要的,除非失去指针,否则它们都将留在Old中。
如果堆栈中没有任何对象引用,这意味着该对象符合垃圾回收的条件。
最后一条对于性能问题非常重要,因此我们需要学习 Java 内存的工作原理以便理解它。
One more room for Metaspace please! 请为 Metaspace 多留一个位置!
Besides these regions, there is one more region in memory I want to mention. ==Metaspace is the region where application’s metadata is stored.==
除了这些区域外,我还想提到内存中的另一个区域:==元空间(Metaspace):是存储应用程序元数据的区域。==
Most of the times, we don’t need to know what is going on in metaspace due to its mission.
大多数时候我们并不需要知道元空间中发生了什么。
And there is one more mission it has and that is holding static variables, methods and classes in it.
但它还有一个使命,那就是保存静态变量、方法和类。
This is why static keyword is accessable from anywhere because they are helding in metaspace so every thread can reach it easily.
这也是为什么静态关键字可以从任何地方访问,因为它们保存在元空间中,所以每个线程都可以轻松访问。
Can we tune this size? 我们能调整这个尺寸吗?
Absolutely. There are flags we can use that tells JVM what to do when we are starting the application. We can some of these flags
当然可以。我们可以使用一些标记来告诉 JVM 在启动应用程序时要做什么。我们可以使用其中一些标志:
- -XmsNg to set initial size
- -XmxNg to set maximum size
- -XX:NewRatio=N ratio of the young generation to the old generation
- -XX:NewSize=N initial size of the young generariton
- -XX:MaxNewSize=N maximum size of the young generation
-XmsNg
:用于设置初始大小。-XmxNg
:用于设置最大大小。-XX:NewRatio=N
:新生代与老年代的 N 比值。-XX:NewSize=N
:新生代的初始大小。-XX:MaxNewSize=N
:年轻代的最大尺寸。
And we’ve reached our deadline. Before we move onto the Garbage Collection, it was essential to learn how Java memory works to have a better understanding about Garbage Collection. I hope I see you in my next article. Happy Coding!
在学习垃圾回收之前,我们有必要了解一下 Java 内存的工作原理,以便更好地理解垃圾回收。希望我们在下一篇文章中再见。编码快乐