模拟JAVA程序内存飙升问题
当使用java开发的程序不是到生产环境上的时候,我们想要排查程序内存或cpu飙升等问题时,可以借助java提供的jstack工具排查高占用的方法代码段。
例如:我们模拟一下程序当中出现死循环时,长时间等待。
编写一个sprngboot的web项目,用于模拟用户请求:
其中写一个controoler类,这个类中包含两个方法,get方法是返回当前请求信息,more方法模拟死循环。
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
@RestController
public class TestController {
@GetMapping("/")
public Object get(){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String remoteAddr = request.getRemoteAddr();
String authType = request.getAuthType();
String remoteUser = request.getRemoteUser();
String remoteHost = request.getRemoteHost();
if (true) {
return String.format("remoteAddr:%s, authType:%s, remoteUser:%s,remoteHost:%s",remoteAddr, authType, remoteUser,remoteHost);
}
return String.valueOf(System.currentTimeMillis());
}
@GetMapping("/more")
public Object more() {
while (true) {
}
}
}
将程序打包部署到服务器,并模拟请求。
启动程序:
java -jar demo-0.0.1-SNAPSHOT.jar
启动完成,程序部署在9091端口
# 模拟请求信息
curl http://127.0.0.1:9091/get
# 模拟请求死循环
curl http://127.0.0.1:9091/more
当执行模拟请求信息时,数据正常返回
curl http://127.0.0.1:9091/get
当我们执行,程序长时间不返回消息,此时已经出现死循环。
curl http://127.0.0.1:9091/more
这时候我们使用top命令查看当前程序占用情况,很明显看到第一条进程号47416记录显示cpu占用100%,这时候我们使用ps命令查看当前进程的线程信息
查看当前进程的线程信息:
# 指令格式
ps -mp pid -o THREAD,tid,time
# 执行指令
ps -mp 47416 -o THREAD,tid,time
看到47437这里执行了4分30秒,很明显是有问题的,这时候我们使用printf将47437转换成16进制数为b94d
printf "%x" 47437
最后一步使用jstack查看详细信息
jstack pid | grep 16进制线程 -A 行数
jstack 47416 | grep 0xb94d -A 20
根据提示信息,出现问题的代码段为com.example.demo.TestController.more(TestController.java:35)
这段代码如下;
@GetMapping("/more")
public Object more() {
while (true) {
}
}