070:jvm内存溢出+调优实战
1 怎样的对象会进入到老年代
课程内容:
1.什么时候会发生full gc
2.死锁问题怎么去定位
3.服务器cpu100%如何定位
4.内存溢出如何去寻找问题
5.jvm调优实际案例分析
什么样的对象进入老年代?
- 大对象;
- 长期存活的对象(默认年龄超过15次、可配置);
- 空间担保 对象太多minor gc s0区、s1区放不下
- 动态年龄 当前Survivor区对应对象年龄有50%>Survivor平均年龄,将大于的部分对象转入老年区
指定创建的对象超过多少会直接创建在老年代
此参数只能在serial收集器和parnew收集器才有效
-XX:PretenureSizeThreshold
(比如 -XX:PretenureSizeThreshold=1M)
指定多大年龄的对象进入老年代
-XX:MaxTenuringThreshold
(比如 -XX:MaxTenuringThreshold=15 默认也是15次)
2 怎么去定位死锁代码
@RestController
public class GCController {
@Value("${mayikt.name}")
private String name;
private List<byte[]> bytes = new ArrayList<>();
@GetMapping("/getName")
public String getName() {
byte[] bytes1 = new byte[1024 * 1024 * 4];
return name;
}
@GetMapping("/deadlock")
public String dieLock() {
new Thread(() -> {
synchronized (Integer.class) {
try {
TimeUnit.SECONDS.sleep(1);
synchronized (String.class) {
System.out.println("执行成功");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
synchronized (String.class) {
try {
TimeUnit.SECONDS.sleep(1);
synchronized (Integer.class) {
System.out.println("执行成功");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "死锁";
}
@GetMapping("/oom")
public String cms() {
List<byte[]> bytes = new ArrayList<>();
while (true) {
byte[] bytes1 = new byte[1024 * 1024 * 4];
bytes.add(bytes1);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@GetMapping("/loop")
public String loop() {
boolean b = true;
while (b) {
}
return "123";
}
@GetMapping("/memoryLeak")
public String oom() {
while (true) {
byte[] bytes1 = new byte[1024 * 1024 * 4];
bytes.add(bytes1);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
本地使用VisualVm查看死锁
定位死锁
控制台输入jsp命令,查看所有java项目pid
jstack pid 打出当前运行的所有线程的快照
死锁只是该线程阻塞,不影响其他线程使用,但是如果死锁的代码一直有请求,最终还是会导致整个服务无法使用(线程池数量有限制)。
3 CPU100%怎么去定位
cpu 100% 定位思路
1.定位到哪一个程序cpu占用率高 top
2.定位到当前程序 是哪一个线程占用率高 ps -mp pid -o THREAD,tid,time,
找到对应tid
3.jstack定位到对应线程快照,打印出的日志搜索tid(转换成16进制)
4 堆内存溢出怎么定位
oom 异常分两种情况
1.内存溢出
2.内存泄漏
内存溢出时候打印堆内存快照
-XX:+HeapDumpOnOutOfMemoryError该配置会把快照保存在用户目录或者tomcat目录下,也可以通过 -XX:HeapDumpPath=/tmp/heapdump.dump来显示指定路径。
Configuration中VM options输入:
-Xloggc:D:\logs\gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump.dump
内存溢出怎么定位:
1.程序里面有大对象;
2.大对象被谁引用,使用visualVM装入dump快照,根据线程快照找到在哪一行出现溢出。
内存泄漏定位:
5 jvm调优案例分析
参考文章:《从实际案例聊聊Java应用的GC优化》
作者:录录 美团技术团队 2017-12-28
链接:从实际案例聊聊Java应用的GC优化.