从0开始,来看看怎么去linux排查Java程序故障

news/2025/2/3 16:42:35/

一,前提准备

最基本前提:你需要有liunx环境,如果没有请参考其它文献在自己得到local建立一个虚拟机去进行测试。

有了虚拟机之后,你还需要安装jdk和配置环境变量

1. 安装JDK(以OpenJDK 17为例)

下载JDK

# 进入用户主目录
cd ~

# 下载OpenJDK 17(以.tar.gz包为例)
wget https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz

# 或Oracle JDK(需官网同意许可协议)
# wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz

 

这里就已经下好了 

 解压并安装

# 创建安装目录(需sudo权限)
sudo mkdir -p /usr/local/java

# 解压JDK到目标目录
sudo tar -xzvf openjdk-17.0.2_linux-x64_bin.tar.gz -C /usr/local/java

# 查看解压后的目录名(例如jdk-17.0.2)
ls /usr/local/java

命令解释

mkdir -p /path/to/directory
  • 递归创建目录:当你指定的路径中某些目录不存在时,mkdir -p 会自动创建这些缺失的父目录。
  • 不会报错:如果目录已经存在,mkdir -p 不会报错,命令会正常执行。
tar -xzvf openjdk-17.0.2_linux-x64_bin.tar.gz -C /usr/local/java

tar -xzvf 是用来解压 .tar.gz.tgz 文件的命令。

  • x:表示 解压(extract)。
  • z:表示 通过 gzip 压缩格式进行解压(unzip the gzip file)。
  • v:表示 显示详细信息,在解压时列出文件名。这个选项是可选的,用来查看解压过程中有哪些文件被处理。
  • f:表示 指定文件,后面需要跟要解压的 .tar.gz 文件名。

2, 配置环境变量

编辑环境变量文件

# 打开用户环境变量配置文件(以bash为例)
nano ~/.bashrc  # 或 ~/.bash_profile、~/.zshrc(根据Shell类型)

命令解释

  • nano:是一个命令行下的文本编辑器。它非常简单,适合快速编辑文件。
  • ~/.bashrc:是当前用户主目录下的 Bash 配置文件。每当你打开一个新的终端时,Bash shell 会加载该文件。在这个文件中,你可以设置环境变量、命令别名、shell 提示符样式等。

添加以下内容到文件末尾

需要注意,不能有空格 

# 手动安装配置
export JAVA_HOME=/usr/local/java/jdk-17.0.2  # 替换为实际解压路径
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

# 包管理器安装配置(若使用方式2)
# export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
# export PATH=$JAVA_HOME/bin:$PATH

 

使配置生效 

source ~/.bashrc  # 根据实际配置文件选择

 验证安装

# 检查Java版本
java -version

# 输出应类似:
openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment (build 17.0.2+8-86)
OpenJDK 64-Bit Server VM (build 17.0.2+8-86, mixed mode)

# 检查JAVA_HOME
echo $JAVA_HOME
# 输出:/usr/local/java/jdk-17.0.2

 

 自动化脚本安装示例:

#!/bin/bash
# 一键安装并配置JDK 17(手动方式)
JDK_URL="https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz"
INSTALL_DIR="/usr/local/java"

# 下载并解压
sudo mkdir -p $INSTALL_DIR
wget $JDK_URL -O /tmp/jdk17.tar.gz
sudo tar -xzvf /tmp/jdk17.tar.gz -C $INSTALL_DIR

# 配置环境变量
echo "export JAVA_HOME=$INSTALL_DIR/$(ls $INSTALL_DIR)" >> ~/.bashrc
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# 验证
java -version

 二,Java代码准备

编写一个简单的让程序不断创建新对象,然后GC在不停地回收,但是又回收不掉地样例。并打包为jar包给到我们的liunx服务器

java">import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;public class Main {// 内存泄漏:让对象无法被GC回收private static final List<byte[]> LEAK_LIST = new ArrayList<>();// CPU密集型任务开关private static final AtomicBoolean RUNNING = new AtomicBoolean(true);public static void main(String[] args) {// 内存泄漏线程:持续分配内存,触发频繁GCnew Thread(() -> {while (true) {// 每次分配1MB内存(不会被回收)LEAK_LIST.add(new byte[1024 * 1024]);try {Thread.sleep(100); // 控制内存分配速度} catch (InterruptedException e) {e.printStackTrace();}}}, "MemoryLeakThread").start();// CPU密集型线程:死循环计算,占用CPUnew Thread(() -> {while (RUNNING.get()) {// 无意义但耗CPU的计算double result = 0;for (int i = 0; i < 100000; i++) {result += Math.sin(i) * Math.cos(i);}}}, "CpuIntensiveThread").start();}
}

打包为可执行jar包

将jar包给到linux

这里我用的vmware的文件共享区进行的共享的。

在虚拟机的设置里面

在选项这里进行配置一下

vmware的文件共享区在Linux中的/mnt/hgfs/ 文件下

 如果/mnt/hgfs 目录为空

  • 可能原因

    • VMware Tools未正确安装。

    • 共享文件夹未启用或配置错误。

    • 自动挂载服务未运行。

解决方案
步骤1:检查VMware Tools状态

# 查看服务是否运行(Ubuntu/Debian)
systemctl status vmware-tools.service

# 重启服务(如果未运行)
sudo systemctl restart vmware-tools.service

如果未安装 VMware Tools则

# 检查 open-vm-tools 状态

systemctl status open-vm-tools

# 若服务存在且未运行,

启动服务

sudo systemctl start open-vm-tools

sudo systemctl enable open-vm-tools

步骤2:手动挂载共享文件夹(临时生效)

# 创建挂载点(若目录不存在)
sudo mkdir -p /mnt/hgfs

# 手动挂载
sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other

#如果因为权限不足,可以加权限

sudo usermod -aG root rojer(rojer是用户名)

步骤3:配置开机自动挂载(永久生效)

# 编辑/etc/fstab文件
sudo nano /etc/fstab

# 添加以下行(保存退出)
.host:/    /mnt/hgfs    fuse.vmhgfs-fuse    allow_other,defaults    0    0

# 重新挂载
sudo mount -a

 准备调试工具

使用阿里的arthas

arthas/README_CN.md at master · alibaba/arthas · GitHub

 下载 Arthas 的 arthas-boot.jar 文件

 curl -O https://arthas.aliyun.com/arthas-boot.jar

 

三,开始测试

使用以下JVM参数启动程序,加速问题暴露(JDK1.8版本):
java -Xms100m -Xmx100m        # 限制堆内存为100MB,加速GC触发
 -XX:+UseG1GC                # 使用G1垃圾回收器(观察GC日志)
 -XX:+PrintGCDetails         # 打印GC详细信息
 -XX:+PrintGCDateStamps      # 显示GC时间戳

 -jar
 GcDemo.jar

Java 9 及以上改用 -Xlog:gc

java -Xms100m -Xmx100m -XX:+UseG1GC -Xlog:gc -jar GCdemo.jar

启动之后问题出现

现象验证方法

观察GC频繁:

1,使用ps -ef | grep java

找到java进程的pid

 

2,通过top命令观察java进程的实时状态

2,使用 jstat -gc <pid> 1000(每秒刷新):

观察GC回收状况,从上面命令可以看出内存资源并不紧张,所以这里只做展示

YGC(Young GC次数)和 FGC(Full GC次数)会快速上升。

从上面可以看出fullGC的次数才3次,且回收时间不大,说明内存情况很健康。又从top中看到cpu资源已经打满,说明有程序在疯狂占用cpu的计算资源。

这里解释一下上图的代表意思

字段说明
S0CSurvivor Space 0 Capacity(幸存区 0 容量),表示幸存区 0 的容量。
S1CSurvivor Space 1 Capacity(幸存区 1 容量),表示幸存区 1 的容量。
S0USurvivor Space 0 Utilization(幸存区 0 使用量),表示幸存区 0 当前使用的内存量。
S1USurvivor Space 1 Utilization(幸存区 1 使用量),表示幸存区 1 当前使用的内存量。
ECEden Space Capacity(伊甸园区容量),表示伊甸园区的容量。
EUEden Space Utilization(伊甸园区使用量),表示伊甸园区当前的使用量。
OCOld Generation Capacity(老年代容量),表示老年代的容量。
OUOld Generation Utilization(老年代使用量),表示老年代当前使用的内存量。
MCMetaspace Capacity(元空间容量),表示元空间的容量。
MUMetaspace Utilization(元空间使用量),表示元空间当前使用的内存量。
CCSCCompressed Class Space Capacity(压缩类空间容量),表示压缩类空间的容量。
CCSUCompressed Class Space Utilization(压缩类空间使用量),表示压缩类空间的当前使用量。
YGCYoung Generation GC Count(年轻代垃圾回收次数),表示年轻代的垃圾回收次数(包括 Minor GC)。
YGCTYoung Generation GC Time(年轻代垃圾回收时间),表示年轻代垃圾回收所花费的时间(单位:秒)。
FGCFull GC Count(Full GC 次数),表示 Full GC(完全垃圾回收)发生的次数。
FGCTFull GC Time(Full GC 时间),表示 Full GC 所花费的时间(单位:秒)。
CGCConcurrent GC Count(并发 GC 次数),表示并发垃圾回收的次数。
CGCTConcurrent GC Time(并发 GC 时间),表示并发垃圾回收的总时间。
GCTTotal GC Time(总垃圾回收时间),表示自启动以来的所有垃圾回收时间(单位:秒)。

详细观察cpu的占用情况

top -p <pid>

然后 按 H(大写的 H)切换到线程视图:

  • 按下 H 键后,top 会从显示进程列表切换到显示线程列表,每个线程会显示为一个单独的条目。

 使用Arthas诊断:

# 1. 启动Arthas
java -jar arthas-boot.jar

这里选择所要监控的程序。

需要注意,如果出现连接异常,且

~/logs/arthas/arthas.log

路径下log中有

Arthas server agent start...

java.lang.OutOfMemoryError: Java heap space

说明你当前的机器在不断消耗内存,导致arthas起不起来!

因为在jvm初始化的时候,这个阶段非常吃内存。

 查看线程CPU占用

# 当前系统的实时数据面板,按 ctrl+c 退出。

dashboard

这里可以看出cpu已经打满,但是堆内存情况良好。

 追踪高cpu线程

thread

参数名称参数说明
id线程 id
[n:]指定最忙的前 N 个线程并打印堆栈
[b]找出当前阻塞其他线程的线程
[i <value>]指定 cpu 使用率统计的采样间隔,单位为毫秒,默认值为 200
[--all]显示所有匹配的线程

 

 这里就已经能定位到问题了。我这个样例比较简单,就一个main类。大家可以构建复杂一点的项目,进行一点点调试看问题。

使用java原生的也能定位到问题。可能比较繁琐一点。

使用 jstack 获取线程堆栈信息

使用 jvisualvm 进行图形化分析

等等。

其它arthas常用方法

  • trace:追踪方法调用的堆栈,帮助你查看方法内部的执行情况。
  • monitor:监控方法的执行,特别是性能问题,像慢方法。
  • stack:查看线程堆栈,特别是线程阻塞和死锁问题。
  • watch:监控方法调用,查看参数和返回值,帮助定位参数错误。
  • heapdump:生成堆转储文件,帮助分析内存问题。
  • jstack:查看 Java 进程的堆栈信息,诊断崩溃或线程死锁。

参考官方文档使用说明!

auth | arthas


http://www.ppmy.cn/news/1569002.html

相关文章

[权限提升] Windows 提权 维持 — 系统错误配置提权 - Trusted Service Paths 提权

关注这个专栏的其他相关笔记:[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01:Trusted Service Paths 提权原理 Windows 的服务通常都是以 System 权限运行的,所以系统在解析服务的可执行文件路径中的空格的时候也会以 System 权限进行解析,如果我们能够利用这一特性,就有…

常见字符串相关题目

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 目录 14.最长公共前缀 5.最长回文子串 67.二进制求和 43.字符串相乘 14.最长公共前缀 题目&#xff1a; 编写一个函数来查…

本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操

本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操 Janus-Pro-7B介绍 Janus-Pro-7B 是由 DeepSeek 开发的多模态 AI 模型&#xff0c;它在理解和生成方面取得了显著的进步。这意味着它不仅可以处理文本&#xff0c;还可以处理图像等其他模态的信息。 模型主要特点:Permalink…

Flink报错Caused by: java.io.FileNotFoundException: /home/wc.txt

当在提交一个flink任务报如下的错误时&#xff1a; Caused by: java.io.FileNotFoundException: /home/wc.txt (没有那个文件或目录)at java.io.FileInputStream.open0(Native Method)at java.io.FileInputStream.open(FileInputStream.java:195)at java.io.FileInputStream.&…

tomcat shutdown.sh不能关闭tomcat 进程

目录 背景及问题表现 处理办法 1、修改setclasspath.sh里的PID环境变量&#xff1a; 背景及问题表现 在上一篇文章中&#xff0c;记录了Debian 12环境里 设置tomcat定时重启的过程&#xff0c;详见&#xff1a;Debian 设定 tomcat 定时重启-CSDN博客 其中我设定的用于重启的…

【力扣】560.和为K的子数组

AC截图 题目 前缀和的概念 首先&#xff0c;我们使用一个叫做“前缀和”的概念。对于数组中的任何位置 j&#xff0c;前缀和 pre[j] 是数组中从第一个元素到第 j 个元素的总和。这意味着如果你想知道从元素 i1 到 j 的子数组的和&#xff0c;你可以用 pre[j] - pre[i] 来计算。…

论文阅读:Realistic Noise Synthesis with Diffusion Models

这篇文章是 2025 AAAI 的一篇工作&#xff0c;主要介绍的是用扩散模型实现对真实噪声的仿真模拟 Abstract 深度去噪模型需要大量来自现实世界的训练数据&#xff0c;而获取这些数据颇具挑战性。当前的噪声合成技术难以准确模拟复杂的噪声分布。我们提出一种新颖的逼真噪声合成…

Kafka 使用说明(kafka官方文档中文)

文章来源&#xff1a;kafka -- 南京筱麦软件有限公司 第 1 步&#xff1a;获取 KAFKA 下载最新的 Kafka 版本并提取它&#xff1a; <span style"color:#000000"><span style"background-color:#f5f2f0"><span style"color:#000000&quo…