JVM
JVM(Java Virtual Machine,Java虚拟机)是一个虚构出来的计算机,通过在真实的计算机上模拟各种计算机功能,本质是一个程序。Java 虚拟机屏蔽了与具体操作系统平台相关的信息,使得 Java 编译器生成的字节码文件,可以在多种平台上不加修改地运行。Java 语言的可移植性正是建立在 Java 虚拟机的基础上。
Java代码编译运行过程:Java源码文件(.java)-> Java编译器 -> 字节码文件(.class)-> JVM -> OS 运行。
1. JVM体系结构
Java 虚拟机主要分为五大模块:类装载器子系统、运行时数据区、执行引擎、本地方法接口和垃圾收集模块。
类装载器子系统:用来加载 .class 字节码文件。
运行时数据区:方法区、堆、虚拟机栈、程序计数器、本地方法栈。
-
方法区是被所有线程共享的运行时内存区域,用于存放被JVM加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
-
堆被所有线程共享,用于存放对象实例。
-
虚拟机栈是线程私有的,生命周期与线程相同。每个方法执行都会创建一个栈帧,用于存放局部变量表,操作栈,动态链接,方法出口等。每个方法从被调用,直到被执行完,对应着一个栈帧在虚拟机中从入栈到出栈的过程。
-
程序计数器用来记录当前线程中正在执行的指令。
-
本地方法栈是线程调用 Native 方法执行时的栈。
执行引擎:执行字节码或本地方法。
本地方法接口:Java 通过 JNI 调用本地 C/C++ 库。
2. 垃圾回收机制
堆是 JVM 进行垃圾回收的主要场所,其次是方法区。Java 将堆内存分为3大部分:年轻代、老年代和永久代,其中年轻代又分为 Eden 区和两个 Survivor 区。
Eden 区主要放新创建的对象,当 Eden 区空间不足时,虚拟机将触发一次 Minor GC。其中一个 Survivor 区保存 Minor GC 幸存下的对象,Eden 区将被清空。每经过一次 Minor GC,对象年龄+1,默认15岁后,该对象就从年轻代转移到老年代。
当老年代空间不足时会触发一次 Full GC。
(1)回收对象
引用计数、可达性分析
(2)回收算法
标记-清除、复制、标记-整理、分代收集
年轻代采用复制算法,老年代采用标记-整理算法。
(3)垃圾收集器
串行收集器、并行收集器、并发收集器
3. JVM监控工具
(1)Jvisualvm
Jvisualvm 是 JDK 自带的一个 JVM 运行监控工具,可用于监视 CPU、堆内存、类加载信息、线程信息等。
如果要监控远程的 tomcat 服务器,则需要配置 catalina.sh 文件。
CATALINA_OPTS="$CATALINA_OPTS \
-Dcom.sun.management.jmxremote \
-Djava.rmi.server.hostname=172.16.10.1 \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false"
(2)Jstat
Jstat 是 JDK 自带的一个轻量级工具,全称 Java Virtual Machine statistics monitoring tool,主要利用 JVM 内建的指令对 Java 应用程序的资源和性能进行实时的命令行的监控,包括了对 Heap size 和垃圾回收状况的监控。
Jstat 可以用来监视 VM 内存中的各种堆和非堆的大小及其内存使用量。
jstat -class <pid>:显示加载 class 的数量及所占空间等信息。
jstat -compiler <pid>:显示 VM 实时编译的数量等信息。
jstat -gc <pid>:可以显示 gc 的信息,查看 gc 的次数及时间。