解密JVM崩溃(Crash)-学习笔记

JVM崩溃例子

代码

java 复制代码
import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @title Crash
 * @description 虚拟机崩溃异常代码:
 * author zzw
 * version 1.0.0
 * create 2024/8/17 21:03
 **/
public class Crash {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        unsafe.getInt(-1);
    }
}

异常日志头部信息

shell 复制代码
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0xf6e6fb3a, pid=16371, tid=0xf6543b40
#
# JRE version: Java(TM) SE Runtime Environment (8.0) (build 1.8.0_401-b10)
# Java VM: Java HotSpot(TM) Server VM (25.401-b10 mixed mode linux-x86 )
# Problematic frame:
# V  [libjvm.so+0x8e9b3a]  Unsafe_GetNativeInt+0xda
#
# Core dump written. Default location: /root/test/core or core.16371
#
# An error report file with more information is saved as:
# /root/test/hs_err_pid16371.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

崩溃日志详解

文件路径

Java程序崩溃时,默认在当前进程运行目录下生成hs_err_pid进程PID.log日志文件。

自定义文件生成位置:-XX:ErrorFile=/Users/zzw/Documents/sourcecode/jvmdir/hs_err_pid%p.log

需要注意的是,如果由于一些异常原因在工作目录无法存储(比如写入权限不足),则该文件会被存储在操作系统的临时目录下。在Linux操作系统环境下,这个地址是**/tmp**。

概要信息

崩溃日志包含系统崩溃时获取到的相关信息,包括但不限于:

  • 导致进行崩溃的异常操作或信号
  • 版本和配置信息
  • 导致进程崩溃的线程的详细信息和线程的堆栈跟踪
  • 正在运行的线程队列及其状态
  • 关于堆的摘要信息
  • 加载的本地库列表
  • 命令行参数
  • 系统变量
  • 关于操作系统和CPU的详细信息

Java虚拟机崩溃时,生产的崩溃日志文件默认会分为4大部分内容

  1. 提供崩溃简要描述的头部信息
  2. 线程信息
  3. 进程信息
  4. 系统信息
头部信息
崩溃原因
shell 复制代码
SIGSEGV (0xb) at pc=0xf6e6fb3a, pid=16371, tid=0xf6543b40
  • SIGSEGV:信号名称
  • (0xb):信号编号
  • 0xf6e6fb3a:程序计数器
  • 16371:进程ID
  • 0xf6543b40:线程ID
问题栈帧

代码崩溃发生的位置

shell 复制代码
# Problematic frame:
# V  [libjvm.so+0x8e9b3a]  Unsafe_GetNativeInt+0xda

**栈帧(frame)**表示程序运行时函数调用栈中的某一帧。

栈帧前面大写字母的特点含义

栈帧(frame)类型 说明 场景
大写字母C Native帧 如第三方动态链接库
小写字母j Java帧 多指未经JIT编译的Java代码
大写字母J Java帧 多指JIT编译后的帧
小写字母v 虚拟机运行时自动生成的帧 如JNI调用、反射、异常处理等部分场景下,虚拟机生成的一小段兼容或优化的桥接代码
大写字母V 虚拟机内部帧 虚拟机内部函数帧
核心转储文件
shell 复制代码
# Core dump written. Default location: /root/test/core or core.16371
  • 完整性和全局视角:操作系统的coredump包含了整个进程的内部转储,包括了JVM本身的内存以及JVM进程所依赖的操作系统资源的状态。这提供了更全面的视角,有助于诊断问题的根源。
  • 内存信息:操作系统的coredump包含了进程的完整内存镜像,包括了堆和栈的信息,这对于分析内存状态以及发现内存相关的问题非常重要。
  • 操作系统资源状态:coredump还可以提供操作系统级别的资源状态信息,比如打开的文件、网络连接等。这些信息可以帮助诊断和解决一些与操作系统资源相关的问题。
  • 与调试器的兼容性:一些调试器可能更喜欢使用操作系统的coredump进行分析和调试。在某些情况下,使用coredump可能更容易进行深入的调试和分析。
线程信息
线程概要
shell 复制代码
---------------  T H R E A D  ---------------

Current thread (0xf6307400):  JavaThread "main" [_thread_in_vm, id=16372, stack(0xf64f4000,0xf6544000)]
  • 0xf6307400:pointer(线程内存指针)

  • JavaThread:type(线程类型)

    • JavaThread
    • VMThread
    • CompilerThread
    • GCTaskThread
    • WatcherThread
    • ConcurrentMarkSweepThread
    • JvmtiAgentThread
    • ServiceThread
    • CodeCacheSweeperThread
    • ...
  • main:name(线程名称)

  • _thread_in_vm:线程状态(仅限Java线程)

    线程状态 说明
    _thread_uninitialized 虚拟机内部创建线程异常状态(可不要关注)
    _thread_new 线程已创建,但是还未执行
    _thread_in_native 线程正在执行native代码
    _thread_in_vm 线程正在执行虚拟机内部代码
    _thread_in_java 线程正在执行Java代码(包括JIT)
    _thread_blocked 线程被阻塞

    极限场景下的一些瞬时中转状态

    线程状态 说明
    _thread_new_trans 正在转变为_thread_new状态
    _thread_in_native_trans 正在转变为_thread_in_native状态
    _thread_in_vm_trans 正在转变为_thread_in_vm状态
    _thread_in_Java_trans 正在转变为_thread_in_java状态
    _thread_blcoked_trans 正在转变为_thread_blocked状态
  • 37696:线程ID

  • stack:线程栈的范围

信号量概要

导致线程终止的意外信号

shell 复制代码
siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0xffffffff

异常码11,它对应的信号量是**SIGSEGV,这是崩溃时最为常见的一种信号量,意味着当前进程正在从非法内存值读取内容(si_addr)。简单来说,每个进程所能读写的内存是有一定范围的,如果超出这个范围进行内存读写是会被操作系统认为是非法的操作。 SIGSEGV同时下面有2种不同的si_code,分别是 SEGV_MAPERR(未映射的地址)、 SEGV_ACCERR**(无效的访问许可)。

寄存器
shell 复制代码
Registers:
EAX=0xf714cbdc, EBX=0xf711aff4, ECX=0xf7157ee0, EDX=0xf6307400
ESP=0xf6542fd0, EBP=0xf6542ff8, ESI=0xf6307400, EDI=0xffffffff
EIP=0xf6e6fb3a, EFLAGS=0x00010a07, CR2=0xffffffff
栈地址
shell 复制代码
Top of Stack: (sp=0xf6542fd0)
0xf6542fd0:   f6307400 f711aff4 f7148688 f6a9fdab
0xf6542fe0:   a3516210 a3516210 f6e6fa6b a3516210
0xf6542ff0:   a3516210 f6307400 f6543034 e730f084
0xf6543000:   f6307540 f654304c ffffffff ffffffff
0xf6543010:   e730ee5b f6543014 a3516210 f654304c
0xf6543020:   a353a130 00000000 a3516210 00000000
0xf6543030:   f6543044 f6543070 e7304b60 00000000
0xf6543040:   e730aad9 ffffffff ffffffff d18c7a88 
指令上下文
shell 复制代码
Instructions: (pc=0xf6e6fb3a)
0xf6e6fb1a:   e4 c7 86 7c 01 00 00 06 00 00 00 89 e2 c1 ea 0c
0xf6e6fb2a:   8d 8b ec ce 03 00 8b 14 91 c6 82 94 01 00 00 01
0xf6e6fb3a:   8b 3f c6 82 94 01 00 00 00 89 7d e4 8b 7e 28 8b
0xf6e6fb4a:   4f 08 8b 57 04 83 39 00 74 28 89 45 d8 50 50 89 
寄存器内容
shell 复制代码
Register to memory mapping:

EAX=0xf714cbdc: <offset 0xbc6bdc> in /root/seckill_server/java/jdk8/jre/lib/i386/server/libjvm.so at 0xf6586000
EBX=0xf711aff4: <offset 0xb94ff4> in /root/seckill_server/java/jdk8/jre/lib/i386/server/libjvm.so at 0xf6586000
ECX=0xf7157ee0: <offset 0xbd1ee0> in /root/seckill_server/java/jdk8/jre/lib/i386/server/libjvm.so at 0xf6586000
EDX=0xf6307400 is a thread
ESP=0xf6542fd0 is pointing into the stack for thread: 0xf6307400
EBP=0xf6542ff8 is pointing into the stack for thread: 0xf6307400
ESI=0xf6307400 is a thread
EDI=0xffffffff is an unknown value
栈帧明细
shell 复制代码
Stack: [0xf64f4000,0xf6544000],  sp=0xf6542fd0,  free space=315k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x8e9b3a]  Unsafe_GetNativeInt+0xda
j  sun.misc.Unsafe.getInt(J)I+0
j  Crash.main([Ljava/lang/String;)V+26
v  ~StubRoutines::call_stub
V  [libjvm.so+0x521d49]  JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)+0xb59
V  [libjvm.so+0x520fde]  JavaCalls::call(JavaValue*, methodHandle, JavaCallArguments*, Thread*)+0x2e
V  [libjvm.so+0x5766f0]  jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*) [clone .constprop.1]+0x260
V  [libjvm.so+0x578239]  jni_CallStaticVoidMethod+0xc9
C  [libjli.so+0x72bc]  JavaMain+0x46c
C  [libpthread.so.0+0x6bbc]  start_thread+0xcc
C  [libc.so.6+0xfe27e]  clone+0x5e

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  sun.misc.Unsafe.getInt(J)I+0
j  Crash.main([Ljava/lang/String;)V+26
v  ~StubRoutines::call_stub
进程信息
进程里的线程

展示了虚拟机内部的Java线程以及其他线程信息。**=>**标识了那个线程是当前的线程

shell 复制代码
---------------  P R O C E S S  ---------------

Java Threads: ( => current thread )
  0xa2fae000 JavaThread "Service Thread" daemon [_thread_blocked, id=16403, stack(0xa3201000,0xa3252000)]
  0xa2f99400 JavaThread "C1 CompilerThread3" daemon [_thread_blocked, id=16402, stack(0xa23ff000,0xa247f000)]
  0xa2f97c00 JavaThread "C2 CompilerThread2" daemon [_thread_blocked, id=16401, stack(0xa2480000,0xa2500000)]
  0xa2f96400 JavaThread "C2 CompilerThread1" daemon [_thread_blocked, id=16400, stack(0xa2780000,0xa2800000)]
  0xa2f94800 JavaThread "C2 CompilerThread0" daemon [_thread_blocked, id=16399, stack(0xa291b000,0xa299b000)]
  0xa2f92c00 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=16398, stack(0xa5e2e000,0xa5e7f000)]
  0xa2f78c00 JavaThread "Finalizer" daemon [_thread_blocked, id=16385, stack(0xa622e000,0xa627f000)]
  0xa2f75c00 JavaThread "Reference Handler" daemon [_thread_blocked, id=16383, stack(0xa642e000,0xa647f000)]
=>0xf6307400 JavaThread "main" [_thread_in_vm, id=16372, stack(0xf64f4000,0xf6544000)]

Other Threads:
  0xa2f70400 VMThread [stack: 0xa3253000,0xa32d3000] [id=16381]
  0xa2fb1800 WatcherThread [stack: 0xa237e000,0xa23fe000] [id=16404]
虚拟机安全状态
shell 复制代码
VM state:not at safepoint (normal execution)
  • not at safepoint:正常状态
  • at safepoint:所有线程处于安全点等待VM进行一些重要的操作,比如GC、Debug等
  • synchronizing:这是一个瞬时的状态。VM等待所有线程到达safepoint,已经达到safepoint的线程会挂起
锁&监视器
shell 复制代码
VM Mutex/Monitor currently owned by a thread: None

当前线程所用于的互斥锁Mutex和监视器Monitor列表。这些互斥锁和监视器是虚拟机内部的锁和监视器,而不是与Java对象相关的锁和监视器。所以却大多数的崩溃文件下,这里输出都是None

内存使用摘要
shell 复制代码
Heap:
 PSYoungGen      total 19200K, used 665K [0xd18c0000, 0xd2e00000, 0xe6e00000)
  eden space 16640K, 4% used [0xd18c0000,0xd19666a0,0xd2900000)
  from space 2560K, 0% used [0xd2b80000,0xd2b80000,0xd2e00000)
  to   space 2560K, 0% used [0xd2900000,0xd2900000,0xd2b80000)
 ParOldGen       total 43776K, used 0K [0xa6e00000, 0xa98c0000, 0xd18c0000)
  object space 43776K, 0% used [0xa6e00000,0xa6e00000,0xa98c0000)
 Metaspace       used 1735K, capacity 2202K, committed 2328K, reserved 4400K
GC辅助模型
shell 复制代码
Card table byte_map: [0xa6bff000,0xa6e00000] byte_map_base: 0xa66c8000

Marking Bits: (ParMarkBitMap*) 0xf714c080
 Begin Bits: [0xa3d00000, 0xa4d00000)
 End Bits:   [0xa4d00000, 0xa5d00000)

卡表是一个标准的空间换时间的解决方案。卡表通常在 JVM 中实现为单字节数组。当我们把 JVM 划分成不同区域的时候,每一个区域(通常是4k字节)就得到了一个标志位。每一位为 1 的时候,表明这个区域为 dirty,持有新生代对象,否则这个区域不持有新生代对象。这样,新生代垃圾收集器在收集live set 的时候,可以通过以下两个操作:

  • 从栈/方法区出发,进入新生代扫描。
  • 从栈/方法区出发,进入老年代扫描,且只扫描 dirty 的区域,略过其他区域。
polling page
shell 复制代码
Polling page: 0xf7768000
  • JIT下虚拟机在指定代码位置完成安全点代码的放置,代码的内容是读取一小块内存(就是这里的polling page)
  • GC时设置这块内存不可读
  • 其他线程代码运行到安全点发现代码不可读,操作系统层面抛出SIGSEGV信号
  • 虚拟机在启动是就完成SIGSEGV信号注册,来监听本次SIGSEGV的内存代码是否是polling page位置
  • 如果是,进程不终止,当前线程进入安全点,线程挂起为后续GC做准备
CodeCache
shell 复制代码
CodeCache: size=245760Kb used=681Kb max_used=681Kb free=245078Kb
 bounds [0xe7300000, 0xe7540000, 0xf6300000]
 total_blobs=170 nmethods=13 adapters=72
 compilation: enabled

首先日志给出了整个CodeCahe的使用情况,第一行给出了总大小(245760kb ),已使用(681Kb ),空闲(245078kb )。第二行用更直观的方式给出了内存上下界(bounds)。以上图为例,这里的0xe7300000代表了CodeCache内存区域的下界,对应的0xf6300000则是内存上界,0xe7540000代表的是已使用内存的边界(可以理解这个边界就是已使用的指针)。

CodeCache内部本质上是各种大小不一的内存块。有的是方法经由JIT编译后的代码,有的是动态生成的元数据等等。当前系统一共有170个内存块,其中13个JIT编译过的方法,以及72个adapters。这些adapters其实是虚拟机内部在解释模式和编译模式下的一种适配,所有方法的默认入口都是解释模式,虚拟机内部会判断当前方法是否已经编译过了,如果已编译则基于adapter路由到已编译的方法,否则继续解释执行

事件分析
编译事件
shell 复制代码
Compilation events (10 events):
Event: 0.036 Thread 0xa2f99400    5       3       java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
Event: 0.037 Thread 0xa2f99400 nmethod 5 0xe73ab608 code [0xe73ab760, 0xe73aba98]
Event: 0.037 Thread 0xa2f99400   10       1       java.lang.ref.Reference::get (5 bytes)
Event: 0.037 Thread 0xa2f99400 nmethod 10 0xe73ab408 code [0xe73ab500, 0xe73ab5a0]
Event: 0.038 Thread 0xa2f99400   11       1       java.lang.ThreadLocal::access$400 (5 bytes)
Event: 0.038 Thread 0xa2f99400 nmethod 11 0xe73ab208 code [0xe73ab300, 0xe73ab380]
Event: 0.038 Thread 0xa2f99400   12       3       java.lang.AbstractStringBuilder::append (50 bytes)
Event: 0.039 Thread 0xa2f99400 nmethod 12 0xe73aa808 code [0xe73aa980, 0xe73aaf10]
Event: 0.039 Thread 0xa2f99400   13       3       java.lang.String::getChars (62 bytes)
Event: 0.039 Thread 0xa2f99400 nmethod 13 0xe73aa188 code [0xe73aa2e0, 0xe73aa5f0]

Compilation events 显示了最近10次从Java字节码编译为机器码的方法。这里有一个需要关注的点:**如果你的机器多次崩溃看到的编译事件都相同,可能意味着JVM正在错误的编译当前方法。**如果不明白为何虚拟机会出现这种错误,你可以尝试重写方法将其简化、拆分等,这将有助于你避免相关的崩溃问题。或者也可以利用虚拟机提供的命令来禁止指定方法的编译,比如:

-XX:CompileCommand="exclude java.util.ArrayList::add"

GC历史事件(GC Heap History)

这里会列举出了系统在崩溃时出现的近10次GC

shell 复制代码
GC Heap History (0 events):
No events
逆优化事件(Deoptimization events)
shell 复制代码
Deoptimization events (0 events):
No events

JIT基于特定条件和假设完成代码编译后,在一些场景下,虚拟机突然发现当前的特定条件和假设不满足,当前编译好的方法如果继续执行会发生一些意料之外的情况,此时虚拟机就会触发自动逆优化,针对已经编译好的方法做特定处理,确保整体运行准确。

内存映射明细
shell 复制代码
f7746000-f775d000 r-xp 00000000 fd:01 2122494                            /usr/lib/libpthread-2.17.so
f775d000-f775e000 r--p 00016000 fd:01 2122494                            /usr/lib/libpthread-2.17.so
f775e000-f775f000 rw-p 00017000 fd:01 2122494                            /usr/lib/libpthread-2.17.so
f775f000-f7762000 rw-p 00000000 00:00 0 
f7762000-f7764000 rw-p 00000000 00:00 0 
f7767000-f7768000 rw-p 00000000 00:00 0 
f7768000-f7769000 r--p 00000000 00:00 0 
f7769000-f776a000 rw-p 00000000 00:00 0 
f776a000-f776b000 r-xp 00000000 00:00 0                                  [vdso]
f776b000-f778d000 r-xp 00000000 fd:01 2122461                            /usr/lib/ld-2.17.so
f778d000-f778e000 r--p 00021000 fd:01 2122461                            /usr/lib/ld-2.17.so
f778e000-f778f000 rw-p 00022000 fd:01 2122461                            /usr/lib/ld-2.17.so
ffbb8000-ffbd9000 rw-p 00000000 00:00 0                                  [stack]
  • [第1列]显示内存区域的起始地址。每个区域代表进程的不同内存映射。
  • [第2列]内存映射区域的访问权限。这里的p代表的是(private)
  • [第5列]指实际在内存中占用的字节数。
  • [第6列]显示内存区域的映射信息,通常包括文件名或其他标识符。如果是匿名内存(未映射到文件),则会显示类似 [heap ]、[stack ]、[anon] 这样的标识。
启动参数&环境变量
shell 复制代码
VM Arguments:
java_command: Crash
java_class_path (initial): .
Launcher Type: SUN_STANDARD

Environment Variables:
PATH=/root/seckill_server/java/jdk8/bin:/usr/local/nginx-1.17.2/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
SHELL=/bin/bash
信号处理
shell 复制代码
Signal Handlers:
SIGSEGV: [libjvm.so+0x922f80], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGBUS: [libjvm.so+0x922f80], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGFPE: [libjvm.so+0x922f80], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGPIPE: [libjvm.so+0x789a50], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGXFSZ: [libjvm.so+0x789a50], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGILL: [libjvm.so+0x922f80], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGUSR1: SIG_DFL, sa_mask[0]=00000000000000000000000000000000, sa_flags=none
SIGUSR2: [libjvm.so+0x789ac0], sa_mask[0]=00000000000000000000000000000000, sa_flags=SA_RESTART|SA_SIGINFO
SIGHUP: [libjvm.so+0x78a1c0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGINT: [libjvm.so+0x78a1c0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGTERM: [libjvm.so+0x78a1c0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGQUIT: [libjvm.so+0x78a1c0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
系统信息
系统信息概要
shell 复制代码
---------------  S Y S T E M  ---------------

OS:CentOS Linux release 7.5.1804 (Core) 

uname:Linux 3.10.0-1160.92.1.el7.x86_64 #1 SMP Tue Jun 20 11:48:01 UTC 2023 x86_64
libc:glibc 2.17 NPTL 2.17 
rlimit: STACK 8192k, CORE infinity, NPROC 63453, NOFILE 65535, AS infinity
load average:0.06 0.33 0.27
系统内存概括
shell 复制代码
/proc/meminfo:
MemTotal:       16264988 kB
MemFree:        10207936 kB
MemAvailable:   12058044 kB
Buffers:           85876 kB
Cached:          1974164 kB
SwapCached:            0 kB
Active:          4048200 kB
Inactive:        1576592 kB
Active(anon):    3565492 kB
Inactive(anon):     8700 kB
Active(file):     482708 kB
Inactive(file):  1567892 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                48 kB
Writeback:             0 kB
AnonPages:       3562968 kB
Mapped:           256152 kB
Shmem:              9444 kB
Slab:             156004 kB
SReclaimable:     106592 kB
SUnreclaim:        49412 kB
KernelStack:       17200 kB
PageTables:        26404 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     8132492 kB
Committed_AS:   13224244 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       34460 kB
VmallocChunk:   34359698612 kB
Percpu:             2560 kB
HardwareCorrupted:     0 kB
AnonHugePages:   1660928 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       89600 kB
DirectMap2M:     4104192 kB
DirectMap1G:    14680064 kB

这些内容其实就是系统崩溃瞬时**cat /proc/meminfo的输出明细。 /proc/meminfo是了解Linux系统内存使用状况的主要接口(需要注意的是在当前的MacOS开发环境并不适用),我们最常用的 free vmstat**等命令就是通过它获取数据的 ,但一般来说在排查一些内存泄漏问题,利用meminfo的输出还是非常有帮助

CPU信息概括
shell 复制代码
CPU:total 8 (initial active 8) (4 cores per cpu, 2 threads per core) family 6 model 106 stepping 6, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, avx, avx2, aes, clmul, erms, rtm, 3dnowpref, lzcnt, ht, tsc, tscinvbit, bmi1, bmi2, adx

/proc/cpuinfo:
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 106
model name      : Intel(R) Xeon(R) Platinum 8378C CPU @ 2.80GHz
stepping        : 6
microcode       : 0x1
cpu MHz         : 2799.998
cache size      : 58368 KB
physical id     : 0
siblings        : 8
core id         : 0
cpu cores       : 4
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 arat avx512vbmi umip avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq md_clear spec_ctrl intel_stibp arch_capabilities
bogomips        : 5599.99
clflush size    : 64
cache_alignment : 64
address sizes   : 42 bits physical, 48 bits virtual
power management:
processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 106
model name      : Intel(R) Xeon(R) Platinum 8378C CPU @ 2.80GHz
stepping        : 6
microcode       : 0x1
cpu MHz         : 2799.998
cache size      : 58368 KB
physical id     : 0
siblings        : 8
core id         : 0
cpu cores       : 4
apicid          : 1
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 arat avx512vbmi umip avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq md_clear spec_ctrl intel_stibp arch_capabilities
bogomips        : 5599.99
clflush size    : 64
cache_alignment : 64
address sizes   : 42 bits physical, 48 bits virtual
power management:

processor       : 2
......

这里其实就是命令**cat /proc/cpuinfo**的输出明细,给出了当前机器的CPU型号、CPU制造商、产品代号、主频、二级缓存、浮点运算单元等信息。

其它信息
shell 复制代码
Memory: 4k page, physical 16264988k(10207936k free), swap 0k(0k free)

vm_info: Java HotSpot(TM) Server VM (25.401-b10) for linux-x86 JRE (1.8.0_401-b10), built on Dec 19 2023 12:38:34 by "java_re" with gcc 11.2.0

time: Sat Aug 17 22:17:51 2024
timezone: CST
elapsed time: 0.043262 seconds (0d 0h 0m 0s)

日志的结尾给出了内存,虚拟机版本等内容,但大多和之前重合,这里有一个有用的信息是elapsed time,它反映了从应用启动到崩溃一共耗时多久(我的例子里直接启动就主动让虚拟机立刻崩溃了所以这里是0)。

解密JVM崩溃(Crash):如何通过日志分析揭开神秘面纱|得物技术

相关推荐
冰帝海岸19 分钟前
01-spring security认证笔记
java·笔记·spring
小二·1 小时前
java基础面试题笔记(基础篇)
java·笔记·python
朝九晚五ฺ3 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
阿龟在奔跑4 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
wusong9994 小时前
mongoDB回顾笔记(一)
数据库·笔记·mongodb
猫爪笔记4 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
Resurgence034 小时前
【计组笔记】习题
笔记
王佑辉4 小时前
【jvm】方法区常用参数有哪些
jvm
王佑辉4 小时前
【jvm】HotSpot中方法区的演进
jvm
pq113_65 小时前
ftdi_sio应用学习笔记 3 - GPIO
笔记·学习·ftdi_sio