JVM内存结构

JVM是java代码的运行环境, 用来加载 .class和jar文件 , 运行代码。

内存区域

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
+------------------------------------------------------+
|                                                      |
|   +-------------+        +---------------+           |
|   | xxxA.class  |        |               |           |
|   | xxxB.class  |  ----> |  class loader | <--+      |
|   |     ...     |        |               |    |      |
|   +-------------+        +---------------+    |      |
|                                               v      |
|  +------------------------------------------------+  |
|  |                                                |  |
|  | +--------+      +------------+ +-------------+ |  |
|  | |  Heap  |      | JVM Stacks | | pc Register | |  |
|  | +--------+      +------------+ +-------------+ |  |
|  |                                                |  |
|  | +--------------+    +----------------------+   |  |
|  | | Method Area  |    | Native Method Stacks |   |  |
|  | +--------------+    +----------------------+   |  |
|  |                                                |  |
|  +--------------Run-Time Data Areas---------------+  |
|                                                      |
|   ^           +-------------------------------+      |
|   |           | native method interface (JNI) |      |
|   |           +-------------------------------+      |
|   |              ^                ^                  |
|   |              |                |                  |
|   |              |                |                  |
|   v              v                v                  |
|  +------------------+  +--------------------------+  |
|  | execution engine |  | native method libraries  |  |
|  +------------------+  +--------------------------+  |
|                                                      |
+------------------------------------------------------+

内存区域与运行关系

  • 堆 Heap
    圾回收的主要区域,又划分为新生代和老年代。
  • 方法区 Method Area
    存放常量池、静态变量、类信息、JIT编译后的代码等数据。
    方法区是虚拟机规范中的概念,而永久代(PermGen)是HotSpot版的方法区。 HotSpot虚拟机从1.8开始取消了永久代,改为元空间(Metaspace)。
  • 本地方法栈 Native Method Stacks
    类似于虚拟机栈
  • 虚拟机栈 Java Virtual Machine Stacks
    每个线程都有,存放着局部变量表,返回值,栈帧等 。局部变量表: 基本数据类型与对象引用 栈帧:方法之间的调用顺序以栈的方式保存。
  • 程序计数器 pc Register
    pc (program counter) 每个线程都有,记录着线程当前运行到哪行代码
  • 运行时常量池 Run-Time Constant Pool
    属于方法区的一部分。

参考 Java运行时数据区


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
+------------------------------------------------+ +------------------------------------------------+
|                                                | |                                                |
|                thread.1                        | |                thread.N                        |
|                                                | |                                                |
+------------------------------------------------+ +------------------------------------------------+
|                pc Register                     | |                pc Register                     |
|                                                | |                                                |
+------------------------------------------------+ +------------------------------------------------+
|                                                | |                                                |
|  +-------------------+  +-------------------+  | |  +-------------------+  +-------------------+  |
|  |                   |  |                   |  | |  |                   |  |                   |  |
|  |    JVM Stacks     |  |   Native Method   |  | |  |    JVM Stacks     |  |   Native Method   |  |
|  |                   |  |       Stacks      |  | |  |                   |  |       Stacks      |  |
|  +-------------------+  +-------------------+  | |  +-------------------+  +-------------------+  |
|  |                   |  |                   |  | |  |                   |  |                   |  |
|  |                   |  |                   |  | |  |                   |  |                   |  |
|  |     +     ^       |  |     +     ^       |  | |  |     +     ^       |  |     +     ^       |  |
|  |     |     |       |  |     |     |       |  | |  |     |     |       |  |     |     |       |  |
|  |     |     |       |  |     |     |       |  | |  |     |     |       |  |     |     |       |  |
|  |     v     +       |  |     v     +       |  | |  |     v     +       |  |     v     +       |  |
|  |                   |  |                   |  | |  |                   |  |                   |  |
|  | +---------------+ |  | +---------------+ |  | |  | +---------------+ |  | +---------------+ |  |
|  | |  stack frame  | |  | |  stack frame  | |  | |  | |  stack frame  | |  | |  stack frame  | |  |
|  | +---------------+ |  | +---------------+ |  | |  | +---------------+ |  | +---------------+ |  |
|  | |     ...       | |  | |     ...       | |  | |  | |     ...       | |  | |     ...       | |  |
|  | +---------------+ |  | +---------------+ |  | |  | +---------------+ |  | +---------------+ |  |
|  | |  stack frame  | |  | |  stack frame  | |  | |  | |  stack frame  | |  | |  stack frame  | |  |
|  | +---------------+ |  | +---------------+ |  | |  | +---------------+ |  | +---------------+ |  |
|  |                   |  |                   |  | |  |                   |  |                   |  |
|  +-------------------+  +-------------------+  | |  +-------------------+  +-------------------+  |
|                                                | |                                                |
|                                                | |                                                |
+------------------------------------------------+ +------------------------------------------------+

+---------all-threads-share------------------------------------+   +--------------------------------+
|                                                              |   |                                |
|  +---method-area--------------+     +---heap--------------+  |   |                                |
|  |                            |     |                     |  |   |      direct memory             |
|  |  class(field, method, ...) |     |                     |  |   |                                |
|  |                            |     |   obj's             |  |   |                                |
|  +----------------------------+     |                     |  |   |                                |
|  |  Run Time Constant Pool    |     |                     |  |   |                                |
|  +----------------------------+     +---------------------+  |   |                                |
|                                                              |   |                                |
+--------------------------------------------------------------+   +--------------------------------+

内存区域与线程关系

  • 如何查看常量池,如何查看运行时常量池
    javap可查看一个类的常量池。
    运行时常量池可通过对内存dump,使用分析工具进行查看对比。

执行引擎

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
+----------Execution Engine----------+
|                                    |
| +-------------+  |---------------+ |
| |             |  |               | |
| | Interpreter |  | JIT Compiler  | |
| |             |  |               | |
| +-------------+  +---------------+ |
|     +------------------------+     |
|     |                        |     |
|     |   Garbage Collection   |     |
|     |                        |     |
|     +------------------------+     |
|                                    |
+------------------------------------+
  • 解释器 Interpreter
    .class代码按顺序解释执行。
    相同Java代码在不同平台下编译后的.class文件相同。 但在运行.class代码时,还是要针对平台解释成不同的机器码的。
  • JIT (Just In Time) Compiler
    将部分热点代码直接编译成机器码,避免了反复通过Interpreter解释执行。
  • 垃圾回收 Garbage Collection
    收集移除无用的对象,释放内存。

JDK, JRE, JVM的区别

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
+-------------------------------------------------------------------------+
|                                                              JDK        |
|                                                                         |
| +---------------------------------------------------+   +-------------+ |
| |                                JRE                |   |             | |
| | +----------------------+                          |   |             | |
| | |                      | +----------------------- |   | development | |
| | |        JVM           | |                      | |   | tools       | |
| | |                      | | set of libraries and | |   | e.g :       | |
| | | java virtual machine | | compiled class files | |   | jstack      | |
| | |                      | |                      | |   | compiler    | |
| | +----------------------+ +----------------------- |   |             | |
| |                                                   |   |             | |
| +---------------------------------------------------+   +-------------+ |
|                                                                         |
|                                                                         |
+-------------------------------------------------------------------------+

gc

gc(Garbage Collector) 垃圾回收器, 对内存中过期对象进行清理,为后续创建对象提供空间。
stw (stop the world) 指所有线程停止工作,垃圾回收器独掌大权,进行垃圾回收。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
+-----heap------------------------------------------+
|                                                   |
| +-------------+----+----+-----------------------+ |
| |             |    |    |                       | |
| |    eden     | s0 | s1 |                       | |
| |             |    |    |                       | |
| +-------------+----+----+-----------------------+ |
|     young generation         old generation       |
| |                       |                       | |
| | <---  minor GC   ---> | <---  major GC   ---> | |
| |                       |                       | |
| | <--------------   full  gc   ---------------> | |
|                                                   |
+---------------------------------------------------+
垃圾回收主要是对位于堆中的对象进行回收,堆分成两部分:年轻代和老年代。
minor GC是对年轻代gc,major GC是对老年代gc。full GC == minor GC + major GC。

起初的垃圾回收,有年轻代和老年代的概念, 对年轻代gc频率高,对老年代gc频率低。 
后来G1将新生代和老年代分成若干个region ,
而ZGC则没有新生代和老年代的概念。

回收逻辑

大部分对象刚创建的时候,JVM会放在Eden区域。
当Eden区域中的对象达到一定的数目的时候,就会进行Minor GC。
在完成垃圾回收后,存活的对象都会被送到某个Suvivor中,两个Suvivor区域总会有一个是空的(s0和s1交替)。
年轻代中经历过了多次垃圾回收,还活着的对象就会转移到年老代中。
当内存不足时,就会镜像full gc, 对整个堆进行垃圾回收。 

垃圾回收器

  • ZGC
  • G1(Garbage-First) 并发
  • 新生代 young generation
    • Serial 串行
    • ParNew 并行
    • Parallel Scavenge 并行
  • 老年代 old generation
    • Serial Old 串行
    • Parallel Old
    • CMS 并发

Concurrent Mark Sweep (CMS) Collector

不同的垃圾回收器会有不同的参数类型配置
在ZGC以前的gc调优有两个方向: 吞吐量优先,响应时间优先。面临着鱼和熊掌不可兼得的困扰。
而ZGC是几乎无停顿的, 同时吞吐量也很高(比g1差点)。
该特性早在Azul JDK的C4 垃圾回收器就有,只不过用户习惯了oracle的jdk。

https://crowhawk.github.io/2017/08/15/jvm_3/
https://crowhawk.github.io/tags/#JVM
http://huzb.me/2019/02/21/CMS-G1%E5%92%8CZGC/

参数配置

在启动JVM虚拟机时,可以通过一些参数设置选用哪个垃圾回收器,
以及对该垃圾回收器,进行具体的配置。

比如: -XX:+UseSerialGC   –XX:+UseG1GC 

那么有哪些参数可以配置呢?
可以到oracle的文档中找
https://docs.oracle.com/en/java/javase/11/gctuning/
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/