开发者学堂课程【JVM 整体架构及内存调优 :JVM 整体架构及内存调优(一)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1207/detail/18174
JVM 整体架构及内存调优
内容介绍
一、JVM 回顾
二、java 虚拟机的内存管理
三、JVM 加载机制详解
四、垃圾回收机制及算法
五、JVM 调优
一、JVM 回顾
JVM 是 java Virtual Machine ( java 虚拟机)的缩写,但实际上其他语言也会用到 JVM,比如 Kafka 的源码 scala。
JVM 是-种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
常见的虚拟机如下:
(1)HotSpot:Oracle/Sun JDK 和 OpenJDK 都使用 HotSpot VM 的相同核心;
(2)J9:J9是 IBM 开发的高度模块化的 JVM;
(3)JRockit:JRockit 与 HotSpot 同属于 Oracle,目前为止 Oracle 一直在推进 HotSpot 与 JRockit 两款各有优势的虚拟机进行融合互补;
(4)Zing:由 Azul Systems 根据 HostPot 为基础改进的高性能低延迟的JVM;
(5)Dalvik:Android 上的 Dalvik 虽然名字不叫 JVM,但就是不折不扣的 JVM。
可根据以下问题来了解整体内容。
问题1:为什么要在程序和操作系统中间添加一个JVM ?
JVM是虚拟机,目前主要讲解 java 层面的作用。java 语言本身上是一个命令对象,进行了充分的抽象化,另外还提供了一些自动内存管理的特征。实际上,这些特征脱离 JVM 在操作系统上实现是不太可能的,所以需要中间的 JVM 作为抽象层。
问题2:应用程序、JVM、 操作系统之间的关系?
有了JVM这一抽象层之后,java 就可以实现跨平台。JVM 只需要保证程序能够正常运行 class 文件、编译 class 文件,然后就可以在 UNIX、Windows、Mac OS 平台上运行。java 跨平台的意义在于通过一次编译之后可以处处运行,即 maven 层下载同一个版本的 jar 包,这个 jar 包可以处处运行,而不需要在每一个平台上进行编译。现在 JVM 也存在一些拓展列表等,编译到最后都是 class 的方式。
如下图:
操作系统通过虚拟机申请内存,实际上是通过操作系统进行分配;操作系统分配内存,包括初始内存和后续分配的内存,最终分配到程序。
程序编译成 class 文件,然后到 JVM,再去调用操作系统的函数。JVM 和操作系统之间除了中间的一个转接的作用之外,还有一些其他的问题。
JVM、JRE、JDK 三者之间的关系可以如下图表示:
JVM、JRE、JDK 三者之间的关系可以用一个包含的关系表示。即JDK包含JRE,同时也包含JVM。
JRE 是 JVM 完成一次编译时需要的一个基本的类库。比如怎么操作文件、怎么连接网络等。而 java 体系是会一次性的将 JVM 所运行、所需要的类库都传递给 JVM,加上一些基础的类库,就成了 java 运行时的环境。这个环境称为JRE。另外,JDK 除了 JRE,还提供了一些非常小的工具,比如 java C ,java jar 这些工具命令。
二、java 虚拟机的内存管理
可以分为:类加载系统,运行时数据区,执行引擎。接下来是本地方法接口,本地方法库等。类加载子系统后面会详细讲解。
运行时数据区实际上就是JVM内存,包括方法区、堆、栈、程序计数器、本地方法栈等。
1.运行时数据区的组成
(1)程序计数器
首先编译完 class 文件之后,会生成一次编码文件。然后程序计数器就是一个指针,即字接码文件。实际上对于操作系统而言,就是一行一行的命令,它需要去按顺序去执行。程序计数器就是用指针去标识它,从而执行到哪一行。
(2)虚拟机栈
虚拟机栈由栈针组成。可以理解为由许多栈针组成的虚拟机栈,而栈针里有常见的局部变量表、操作主栈、动态验机,方法出口等。另外虚拟机栈实际上是一个线程私有的,包括栈针里面成员组成、局部变量、操作栈、动态连接、方法出口等是线程私有的。
除了虚拟机栈之外,还有程序计数器也是线程私有的。因为程序计数器实际上也是现成的一个维度,需要去执行程序,最终执行了哪一行。
(3)本地方法栈
本地方法栈也是线程私有的,跟虚拟机栈不同的是,它调用的是 native 方法。native 方法就是 JVM 底层的一些接口,C++的接口。点开源码会经常看到带有 native 标识的东西。
(4)堆
是线程共享的。堆内存是一个最复杂的一个内存结构。它会帮忙保存对象实例,里面会有年轻代、老年代、伊甸园区等。后续的排查问题,包括对内存的使用、优化等都是在这里面去操作的。
(5)方法区
是线程共享的。方法区主要存储一些已被虚拟机加载的一些类信息,常量、静态变量等。例如虚拟站有个 -Xs,则可以去指点群体栈的大小;还有堆 -Xms 等为 JVM 的一些参数。