JAVA中有哪些内存泄漏和内存泄漏?有什么联系和区别?让我们看一下。
汤姆猫:手撕式分布式技术:限流,通讯,缓存,全都在您手中!
Tom cat:采访列表(Java post):Java + JVM ++算法+ Spring +中间件+设计模式

内存泄漏和内存溢出
1.内存泄漏(内存泄漏)
如果内存用完,将不会释放。例如,总共有1024M内存,而尚未回收分配的521M内存。那么可用内存只有521M,好像它的一部分已经泄漏了;
用外行的话来说,内存泄漏是[占用了坑,没有把它拉起来]。

2.内存不足(内存不足)
申请内存时,可用内存不足;
用外行的话来说,厕所里有三个坑,其中两个站在坑中(内存泄漏),最后一个坑被留下了。厕所表明接收压力很高。这时,两个人来了。 ,坑(内存)不足,内存泄漏变成内存溢出。
可以看出内存泄漏和内存溢出之间的关系:内存泄漏的增加最终将导致内存溢出。
这是一个很好的例子。


如上所示:
对象X指向对象Y,并且X的生命周期比Y的生命周期长;

然后,当Y的生命周期结束时,X仍然引用Y。这时,在垃圾回收期间将不回收对象Y;
如果对象X仍然引用生命周期相对较短的A,B和C,而对象A引用了对象a,b和c,则可能导致大量无用的对象无法回收,因此占用内存资源。导致内存泄漏,直到内存溢出。
泄漏的分类是导致内存泄漏的常见原因
1.循环或无限循环太多,导致对象数量众多;
2.静态收集类导致内存泄漏。由于静态集合的生命周期与JVM一致,因此无法释放静态集合引用的对象。在以下示例中,列表是静态的。只要JVM继续运行,obj它将永远不会被释放。
public class OOM { static List list = new ArrayList(); public void oomTests(){ Object obj = new Object(); list.add(obj); }}3.单例模式类似于导致内存泄漏的静态集合。由于单例的静态特性,其生命周期与JVM一样长,因此,如果单例对象包含外部对象Reference,则外部对象将不会被回收,这将导致内存泄漏。
4.数据连接,IO,套接字连接等,必须将它们显示为要释放(用代码关闭),否则它们将不会被GC回收。
try { Connection conn = null; Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("url","", ""); Statement stmt = conn.createStatement() ; ResultSet rs = stmt.executeQuery("....") ; } catch (Exception e) { //异常日志} finally { //1.关闭结果集 Statement //2.关闭声明的对象 ResultSet //3.关闭连接 Connection}
5.如果内部类的对象被保留了很长时间,那么内部类对象所属的外部类对象将不会被回收。
6.哈希值更改,例如以下类,其hashCode将随着变量x的更改而更改:
public class ChangeHashCode { private int x ; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ChangeHashCode other = (ChangeHashCode) obj; if (x != other.x) return false; return true; } //省略 set 、get 方法}public class HashSetTests { public static void main(String[] args){ HashSet hs = new HashSet(); ChangeHashCode cc = new ChangeHashCode(); cc.setX(10);//hashCode = 41 hs.add(cc); cc.setX(20);//hashCode = 51 System.out.println("hs.remove = " + hs.remove(cc));//false hs.add(cc); System.out.println("hs.size = " + hs.size());//size = 2 }} 如您所见,在测试方法中,当元素的hashCode更改时,不再找到更改前的元素;
这就是为什么将String设置为不可变类型的原因。我们可以安全地将String存储在HashSet中,或将String用作HashMap的键值;
当我们要将自己定义的类保存到哈希表时,我们需要确保对象的hashCode是不可变的。
7.内存中加载的数据量太大;当上一个项目启动一次时,应用程序启动直到崩溃都非常缓慢,因为代码会将表中的数据加载到缓存(内存)中,测试环境中只有几百个数据,但是生产环境中有几百万条数据。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-362168-1.html
你好帅