k8s、linux、docker、springboot、springcloud、 jdk1.8
直接输入jvisualvm
jvisualvm


@GetMapping("/hello")
public void getInfo2() throws InterruptedException {
Set<MyObject> objects = new LinkedHashSet<MyObject>();
objects.add(new MyObject());
objects.add(new MyObject());
objects.add(new MyObject());
System.out.println(objects.size());
while(true){
objects.add(new MyObject());
System.out.println(objects.size());
Thread.sleep(100L);
}
}
static class MyObject{
//设置默认数组长度为99999更快的发生OutOfMemoryError
List<String> list = new ArrayList<>(10000);
}


注:当内存到达限制后,会进行内存堆栈的导出,所以这个方法执行会非常久(我配置是最大4G内存)

k8s 控制台执行如下命令
kubectl -n lc top pods

cpu和内存不断飙高,等服务报内存溢出后,直接去容器内部把堆栈文件下载下来。
拷贝命令如下:
cp lc/sx-system-deployment-58d67dbdd4-vdwc2:/sx/java_pid1.hprof /root/java_pid1.hprof
所在容器目录:

装入


查找
找到占用最大的对象

右键–》在实例视图中显示

找到问题代码

堆内存增长查看要用如下命令
jmap -heap pid

package test.oom;
public class StackOOM {
private int stackLength = 1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable {
StackOOM oom = new StackOOM();
try {
oom.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
}

@GetMapping("/hello1")
public void getInfo3() throws InterruptedException {
CpuTest myThread1 = new CpuTest();
CpuTest myThread2 = new CpuTest();
CpuTest myThread3 = new CpuTest();
CpuTest myThread4 = new CpuTest();
myThread1.start();
myThread2.start();
myThread3.start();
myThread4.start();
}
class CpuTest extends Thread {
@Override
public void run() {
int i = 0;
while (true) {
i++;
}
}
}
方法1
kubectl -n lc top pods
查看到CPU会飙到limits限制的临界点

方法2
1.先在宿主机上使用top命令查出占用CPU高的进程id
2.通过使用以下命令查出对应的容器
docker ps -q | xargs docker inspect --format '{{.State.Pid}} {{.Name}}' | column -t|grep PID
查找到占CPU的线程
方法1 利用arthas工具
java -jar /opt/arthas/arthas-boot.jar
进入arthas 界面后,输入dashboard


得到占CPU严重的是线程
方法1
在arthas 中直接使用thread ID(该ID为上一步取得的id)

方法2
通过spring boot admin 查看导致CPU 占满的代码

除了用第12步骤的方法外,还可以用以下这种方法
1.查询虚拟机运行参数信息。
jinfo -flags pid
2.输出堆内存设置和使用情况(JDK11使用jhsdb jmap --heap --pid pid)
jmap -heap pid
3.用于输出运行主类的全名
jps -l
4.生成堆栈快照
jmap -dump:format=b,file=2020.dump pid
5.查询虚拟机当前的线程快照信息
jstack -l pid
jstack -l pid >> 文件名
6.从容器中拷贝文件到宿主机
kubectl cp lc/sx-system-deployment-58d67dbdd4-vdwc2:/sx/java_pid1.hprof /root/java_pid1.hprof
7.通过pid 查找容器名称
nsenter --pid --uts -t 145483 hostname
