第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > java内存泄露和内存溢出

java内存泄露和内存溢出

时间:2023-03-05 11:40:15

相关推荐

java内存泄露和内存溢出

内存泄露

是指:对象没有被用到,但是又无法被GC回收就是内存泄露;分类:经常发生: 发生内存泄露的代码会被多次执行,每次执行,泄露一块内存偶然发生: 在某些特定情况下才会发生一次性: 发生内存泄露的方法只会执行一次隐式泄漏: 一直占着内存不释放,直到执行结束; 严格的说这个不算内存泄漏,因为最终释放掉了, 但是如果执行时间特别长,也可能会导致内存耗尽

内存溢出

申请内存时候 没有足够得内存被使用就是内存溢出;

通常内存泄露导致内存溢出;

内存泄露案例

静态集合类

如HashMap、LinkedList等等。如果这些容器为静态的,那么它们的生命周期与JVM程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。简单而言,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

public class test {static List list = new ArrayList<>();public void oomTest() {Object object = new Object();list.add(object);}}

内部类持有外部类

如果一个外部类的实例对象的方法返回了一个内部类的实例对象。这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄漏。

各种连接,如数据库连接、网络连接和IO连接等

在对数据库进行操作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。否则,如果在访问数据库的过程中,对Connection、 Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而引起内存泄漏。

public class test {public static void main(String[] args) {try {Connection conn = null;Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("url","","");Statement statement = conn.createStatement();ResultSet resultSet = statement.executeQuery();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();}finally {//1. 关闭结果集 statement//2. 关闭声明的对象 resultSet//3. 关闭连接 Connection}}

变量不合理的作用域

一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另一方面,如果没有及时地把对象设置为null,很有可能导致内存泄漏的发生。

public class test {private String msg;public void receiveMsg(){readFromNet();//从网络中接受数据保存到msg中saveDB();//把msg保存到数据库中}}

缓存泄漏

内存泄漏的一个常见来源是缓存,一旦你把对象引用放入到缓存中,就很容易遗忘。比如:之前项目在一次上线的时候,应用启动奇慢直到夯死,就是因为代码中会加载一个表中的数据到缓存(内存)中,测试环境只有几百条数据,但是生产环境有几百万的数据。|

对于这个问题,可以使用WeakHashMap(弱引用)代表缓存,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值。

总之被分为:

1.原本不需要那么长周期的对象 周期太长,例如案例124

2.连接数据库、网络请求、读结果集 没有关闭连接 导致GC无法回收 例如3;

3.一次取得对象太多,大量并发时候 内存不够,超过10万条 建议用分页 例如5;

内存溢出报错:

内存溢出有以下几种常见的情况:

1、java.lang.OutOfMemoryError: PermGen space (持久带溢出)

我们知道jvm通过持久带实现了java虚拟机规范中的方法区,而运行时常量池就是保存在方法区中的,因此发生这种溢出可能是运行时常量池溢出,或是由于程序中使用了大量的jar或class,使得方法区中保存的class对象没有被及时回收或者class信息占用的内存超过了配置的大小。

2、java.lang.OutOfMemoryError: Java heap space (堆溢出)

发生这种溢出的原因一般是创建的对象太多,在进行垃圾回收之前对象数量达到了最大堆的容量限制。解决这个区域异常的方法一般是通过内存映像分析工具对Dump出来的堆转储快照进行分析,看到底是内存溢出还是内存泄漏。如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链,定位出泄漏代码的位置,修改程序或算法;如果不存在泄漏,就是说内存中的对象确实都还必须存活,那就应该检查虚拟机的堆参数-Xmx(最大堆大小)和-Xms(初始堆大小),与机器物理内存对比看是否可以调大

避免内存泄漏的几点建议:

1、局部变量就不要定义成全局变量,减小对象周期。

2、避免在循环中创建对象。

3、使用字符串处理时避免使用String,应使用StringBuffer。

4、尽量少使用静态变量,因为静态变量存放在永久代,基本不参与垃圾回收。

5、取大量数据建议分页;

6、数据库、网路等记得关闭连接;

*自己总结:

问:什么情况下会产生内存溢出,我们开发中应该怎么避免?怎么判断?

答:

集合类定义成了静态变量、内部类被使用外部类、变量定义在全局变量中 导致生命周期拉长从数据库中一次去除大量数据连接网络数据库没有及时关闭无法回收。

判断:

看报错 持久性报错就是 引入的jar包太多或者class文件太多

堆溢出 对象太多 可能是代码问题 也可能内存设置的太少*

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。