《极客时间教程 - 深入拆解 Java 虚拟机》笔记
开篇词 为什么我们要学习 Java 虚拟机?
Java 代码是怎么运行的?
从虚拟机视角来看,执行 Java 代码首先需要将它编译而成的 class 文件加载到 Java 虚拟机中。加载后的 Java 类会被存放于方法区(Method Area)中。实际运行时,虚拟机会执行方法区内的代码。
从虚拟机视角来看,执行 Java 代码首先需要将它编译而成的 class 文件加载到 Java 虚拟机中。加载后的 Java 类会被存放于方法区(Method Area)中。实际运行时,虚拟机会执行方法区内的代码。
略
JVM - Java Virtual Machine 的缩写,即 Java 虚拟机。JVM 是运行 Java 字节码的虚拟机。JVM 不理解 Java 源代码,这就是为什么要将 *.java
文件编译为 JVM 可理解的 *.class
文件(字节码)。Java 有一句著名的口号:“Write Once, Run Anywhere(一次编写,随处运行)”,JVM 正是其核心所在。实际上,JVM 针对不同的系统(Windows、Linux、MacOS)有不同的实现,目的在于用相同的字节码执行同样的结果。
JVM 能跨平台工作,主要是由于 JVM 屏蔽了与各个计算机平台相关的软件、硬件之间的差异。
真实的计算机体系结构的核心部分包含:
JVM 体系结构与计算机体系结构相似,它的核心部分包含:
Java 程序员免不了故障排查工作,所以经常需要使用一些 JVM 工具。
JDK 自带了一些实用的命令行工具来监控、分析 JVM 信息,掌握它们,非常有助于 TroubleShooting。
以下是较常用的 JDK 命令行工具:
名称 | 描述 |
---|---|
jps |
虚拟机进程状况工具。显示系统内的所有 JVM 进程。 |
jstat |
JVM 统计监控工具。监控虚拟机运行时状态信息,它可以显示出 JVM 进程中的类装载、内存、GC、JIT 编译等运行数据。 |
jmap |
JVM 堆内存分析工具。用于打印 JVM 进程对象直方图、类加载统计。并且可以生成堆转储快照(一般称为 heapdump 或 dump 文件)。 |
jstack |
JVM 栈查看工具。用于打印 JVM 进程的线程和锁的情况。并且可以生成线程快照(一般称为 threaddump 或 javacore 文件)。 |
jhat |
用来分析 jmap 生成的 dump 文件。 |
jinfo |
JVM 信息查看工具。用于实时查看和调整 JVM 进程参数。 |
jcmd |
JVM 命令行调试 工具。用于向 JVM 进程发送调试命令。 |
Java 应用出现线上故障,如何进行诊断?
我们在定位线上问题时要有一个整体的思路,顺藤摸瓜,才能较快的找到问题原因。
一般来说,服务器故障诊断的整体思路如下:
JVM 在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。如下图所示:
类是在运行期间动态加载的。
类的加载指的是将类的 .class
文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class
对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class
对象,Class
对象封装了类在方法区内的数据结构,并且向 Java 程序员提供了访问方法区内的数据结构的接口。
程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收。垃圾回收主要是针对 Java 堆和方法区进行。
引用计数算法(Reference Counting)的原理是:在对象中添加一个引用计数器,每当有一个地方 引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。
【Java 虚拟机】总结、整理了个人对于 JVM 的学习、应用心得。
程序计数器
、虚拟机栈
、本地方法栈
、堆
、方法区
、运行时常量池
、直接内存
、OutOfMemoryError
、StackOverflowError
GC Roots
、Serial
、Parallel
、CMS
、G1
、Minor GC
、Full GC
bytecode
、asm
、javassist
ClassLoader
、双亲委派
jps
、jstat
、jmap
、jstack
、jhat
、jinfo
、jconsole
、jvisualvm
、MAT
、JProfile
、Arthas
CPU
、内存
、磁盘
、网络
、GC
配置
、调优
Java 字节码是 Java 虚拟机执行的一种指令格式。之所以被称之为字节码,是因为:Java 字节码文件(.class
)是一种以 8 位字节为基础单位的二进制流文件,各个数据项严格按照顺序紧凑地排列在 .class 文件中,中间没有添加任何分隔符。整个 .class 文件本质上就是一张表。
Java 能做到 “一次编译,到处运行”,一是因为 JVM 针对各种操作系统、平台都进行了定制;二是因为无论在什么平台,都可以编译生成固定格式的 Java 字节码文件(.class
)。