public class User {
private int id;
private String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
import java.util.ArrayList;
import java.util.List;
public class Memory {
//-Xmx10m -Xms10m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
// -XX:HeapDumpPath=/f:
public static void main(String[] args) {
List<User> list = new ArrayList<>();
while (true) {//死循环
list.add(new User(1,new String("name")));
}
}
}
加参数运行,因为会有死循环创建对象而且不会被垃圾回收,频繁FullGC,会出现OOM异常
因为我们加了打dump文件的参数,会将内存溢出的dump文件打到F盘,这时会在F盘出现一个.hprof后缀名的文件
我们使用jvm自带的工具jvisualvm装入文件可以很明显的看见哪个类的对象占用了多少内存
如图String对象和User对象占用了90%多的内存,我们在程序中也可以看到,此时就大致可以找到内存溢出的原因了。
下面我们来谈一下死锁问题:
产生死锁的四个必要条件:
互斥,占有等待,不可抢占,循环等待
看一段死锁的代码
import java.util.concurrent.TimeUnit;
public class DeadLock {
private static Object object1 = new Object();
private static Object object2 = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (object1) {
System.out.println("object1");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object2) {
System.out.println("object2");
}
}
}).start();
new Thread(() -> {
synchronized (object2) {
System.out.println("object2");
synchronized (object1) {
System.out.println("object1");
}
}
}).start();
}
}
运行这段程序会出现死锁问题
分析如果我们在程序中一不小心就写了一段死锁代码,但是我么自己还不知道程序会一直阻塞在那里,我们应该如何分析原因和定位死锁代码呢?
第一种方法:打开jvisualvm会自动检测到每个进程,可以看到
我们点击线程Dump可以看到最后
可以看到线程发生死锁的具体代码行数,我们就可以定位到了死锁。
第二种方法:
打开cmd,使用jps查看所有的java进程
使用jstack 进程号(这里是15588)
会得到和第一种同样的信息。