场景
用动态存储分配函数动态开辟的空间,在使用完毕后未被释放,结果导致一直占据该内存单元,一直持续到程序结束,即所谓内存泄漏。
静态集合类
生命周期与JVM程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。
长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用但是因为长生命周期对象持有它的引用而导致不能被回收。
单例模式
和静态集合导致内存泄露的原因类似,因为单例的静态特性,它的生命周期和JVM的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏。
内部类持有外部类
内部类持有外部类,如果一个外部类的实例对象的方法返回了一个内部类的实例对象。这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄漏。
各种连接,如数据库连接、网络连接和IO连接等
变量不合理的作用域
变量不合理的作用域。一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另一方面,如果没有及时地把对象设置为null,很有可能导致内存泄漏的发生。
改变哈希值
改变哈希值,当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了。否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄漏。
这也是String为什么被设置成了不可变类型,我们可以放心地把String存入HashSet,或者把String当做HashMap的key值
大分页
大数据量的excel 导入导出
模拟内存溢出
-Xms30M -Xmx30M -Xlog:gc:log/gc-oomHeap.log -XX:MetaspaceSize=64m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap/heapdump.hprof
-Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
public class GCTest {
public static void main(String[] args) {
ArrayList<byte[]> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
byte[] arr = new byte[1024 * 500 ];//50KB
list.add(arr);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
MAT
jvisualvm
装入