java内存泄漏与内存溢出
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!
以发生的方式来分类,内存泄漏可以分为4类:
1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
2. 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
3. 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
4. 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到
一、Java内存回收机制
不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址。Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Heap)中分配的,所有对象的回收都是由Java虚拟机通过垃圾回收机制完成的。GC为了能够正确释放对象,会监控每个对象的运行状况,对他们的申请、引用、被引用、赋值等状况进行监控,Java会使用有向图的方法进行管理内存,实时监控对象是否可以达到,如果不可到达,则就将其回收,
二、Java内存泄露引起原因
内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你Out of memory。
那么,Java内存泄露根本原因是什么呢?长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。具体主要有如下几大类:
1、静态集合类引起内存泄露:
像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。
1 Static Vector v = new Vector(10); 2 for (int i = 1; i<100; i++) 3 { 4 Object o = new Object(); 5 v.add(o); 6 o = null; 7 }//
在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身(o=null),那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null。
2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。
1 public static void main(String[] args) 2 { 3 Set<Person> set = new HashSet<Person>(); 4 Person p1 = new Person("唐僧","pwd1",25); 5 Person p2 = new Person("孙悟空","pwd2",26); 6 Person p3 = new Person("猪八戒","pwd3",27); 7 set.add(p1); 8 set.add(p2); 9 set.add(p3); 10 System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素! 11 p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变 12 13 set.remove(p3); //此时remove不掉,造成内存泄漏 14 15 set.add(p3); //重新添加,居然添加成功 16 System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素! 17 for (Person person : set) 18 { 19 System.out.println(person); 20 } 21 }
3、监听器
在java 编程中,我们都需要和监听器打交道,通常一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXListener()等方法来增加监听器,但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。
4、各种连接
比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。对于Resultset 和Statement 对象可以不进行显式回收,但Connection 一定要显式回收,因为Connection 在任何时候都无法自动回收,而Connection一旦回收,Resultset 和Statement 对象就会立即为NULL。但是如果使用连接池,情况就不一样了,除了要显式地关闭连接,还必须显式地关闭Resultset Statement 对象(关闭其中一个,另外一个也会关闭),否则就会造成大量的Statement 对象无法释放,从而引起内存泄漏。这种情况下一般都会在try里面去的连接,在finally里面释放连接。
6、单例模式
如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露。
如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露
不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:
1 class A{ 2 public A(){ 3 B.getInstance().setA(this); 4 } 5 .... 6 } 7 //B类采用单例模式 8 class B{ 9 private A a; 10 private static B instance=new B(); 11 public B(){} 12 public static B getInstance(){ 13 return instance; 14 } 15 public void setA(A a){ 16 this.a=a; 17 } 18 //getter... 19 }
显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况
转载于:https://www.cnblogs.com/Nick7/p/11184817.html
java内存泄漏与内存溢出相关推荐
- java 内存溢出 内存泄露_JVM——内存泄漏与内存溢出
1.内存溢出 1.1 什么是Java的内存溢出? 在Java程序运行的过程中,经常会碰到以下错误:java.lang.OutOfMemoryError. 通俗讲,内存溢出是指程序在申请内存时,没有足够 ...
- java内存泄漏和内存溢出_Java和内存泄漏
java内存泄漏和内存溢出 总览 术语"内存泄漏"在Java中的使用方式不同于在其他语言中使用的方式. 通用术语中的"内存泄漏"是什么意思,在Java中如何使用 ...
- 透彻分析JAVA内存泄漏和内存溢出的区别
JAVA内存泄漏和内存溢出的区别和联系 1.内存泄漏memory leak : 是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出. 2 ...
- java内存泄漏和内存溢出
java内存泄漏和内存溢出 概念 a)内存泄露:被分配对象可达但无用 b)内存溢出:无法申请到足够的内存而产生的错误 内存泄漏场景 a)创建和应用生命周期一样的单例对象 b)创建匿名内部类的静态对象 ...
- JAVA内存泄漏和内存溢出的区别和联系
内存泄漏和内存溢出的区别与解决方式_jie1175623465的博客-CSDN博客_内存泄露和内存溢出是指什么,它们有什么区别 内存泄漏(memory leak ) 内存溢出 (out of memo ...
- python会不会出现内存泄露_Python内存泄漏和内存溢出的解决方案
一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...
- python会内存泄漏吗_Python内存泄漏和内存溢出的解决方法
Python内存泄漏和内存溢出的解决方法 发布时间:2020-10-30 23:08:34 来源:亿速云 阅读:92 作者:Leah 这篇文章将为大家详细讲解有关Python内存泄漏和内存溢出的解决方 ...
- python 内存溢出能捕获吗_Python内存泄漏和内存溢出的解决方案
一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...
- python内存泄漏解决方案_Python内存泄漏和内存溢出的解决方案
一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...
- 移动端测试=== 两个概念 内存泄漏 和 内存溢出 【转】
关于内存在一块其实我并不是很想拿出来说,一般情况下内存这一块都是可优化的,可以通过硬件资源或者调整一些系统或者应用系统的参数配置来进行优化. 很多同僚问到了"内存泄漏"和" ...
最新文章
- git中的fork应该这样使用
- Android之linux基础教学之一 内存地址
- 移动端重构系列1——前期准备工作
- linux系统中查看己设置iptables规则
- Spring 执行 sql 脚本(文件)
- CLion运行python程序
- 使用GPUImage实现视频滤镜
- Python网络编程(1)-socket
- 原根(详解+代码实现+例题+快速求解一个数的原根)
- ora-07445 oracle 9,Oracle ORA-07445 : 出现异常错误: 核心转储(一)
- 发送和接收_通用异步接收器/发送器(UART)
- win10你的电脑设备需要修复_cf挑战辅助w10蓝屏后若何用命令提示符修复
- LeetCode——Find Minimum in Rotated Sorted Array II
- maven修改本地仓库地址配置文件
- 这是我的计算机房英语怎么写,小学英语人教(12版三起点)四年级下册Unit 1
- 35岁中年程序员的焦虑和64岁谷歌老程序员的补丁
- python的easyocr图像文字识别
- Python Flask学习_使用flask-login实现认证蓝本(一)
- 网页POST之文件上传专项视频教程
- 如何科学增长邮件订阅用户?
热门文章
- sql2017 for linux,Installing SQL Server 2017 for Linux on Ubuntu 18.04 LTS
- springboot thymeleaf配置_【程序源代码】Spring Boot 开发笔记web开发实战1
- 计算机组成原理2010年,2010年计算机组成原理考研试题及解答
- AtCoder Beginner Contest 223
- java第七章第九题_Java2程序设计基础第七章课后习题
- AtomicInteger原子整形与ReentrantLock锁
- DOM-window下的常用子对象-location-刷新页面
- C# 在数组中判断是否存在某个数组值
- OpenvSwitch readme faq
- ASP.NET中Session的sessionState 4种mode模式