Java刷题知识点之内存溢出和内存泄漏的概念、区别、内存泄露产生原因、内存溢出产生原因、内存泄露解决方案、内存溢出解决方案

简介:

内存溢出和内存泄漏的区别

    内存泄漏指你用malloc或new申请了一块内存,但是没有通过free或delete将内存释放,导致这块内存一直处于占用状态。
 内存溢出指你申请了10个字节的空间,但是你在这个空间写入11或以上字节的数据,就是溢出。

    内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。

  内存泄露 (memory leak),是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

   内存溢出( out of memory),是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
  注意:memory leak会最终会导致out of memory!

        内存泄露最终会导致内存溢出。
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。

 

 

  相同点:都会导致应用程序运行出现问题,性能下降或挂起。

       不同点

          1) 内存泄露是导致内存溢出的原因之一;内存泄露积累起来将导致内存溢出

          2) 内存泄露可以通过完善代码来避免;内存溢出可以通过调整配置来减少发生频率,但无法彻底避免

 

 

 

 

 

引起内存泄露的原因:

  (1)静态集合类,例如HashMap和Vector。如果这些容器为静态的,由于它们的生命周期与程序一致,那么容器中的对象在程序结束之前将不能被释放,从而造成内存泄露。

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

  (3)监听器。在Java语言中,往往会使用到监听器。通常一个应用中会用到多个监听器。但在释放对象的同时往往没有相应地删除监听器,这也可能导致内存泄露。

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

 

 

 

 

 

 

引起内存溢出的原因

  1、内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2、集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3、代码中存在死循环或循环产生过多重复的对象实体;
4、使用的第三方软件中的BUG;
5、启动参数内存值设定的过小

 

 

 

 

内存泄漏可以分为4类

  1)  常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

  2)  偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。

  3)  一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。

  4)  隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

 

 

 

 

 

内存溢出的解决方案
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

 

    

  一是从代码层面进行优化完善,尽量避免该情况发生;

        二是调整优化服务器配置: 

          1) 设置-Xms、-Xmx相等;

          2)  设置NewSize、MaxNewSize相等;

          3) 设置Heap size, PermGen space:

            Tomcat 的配置示例:修改 %TOMCAT_HOME%/bin/catalina.bat or catalina.sh

            在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:

Cmd代码 set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

 

 

 

Java中会存在内存泄漏吗?

  Java中也存在内存泄露。当被分配的对象可达但已无用(未对作废数据内存单元的引用置null)即会引起。

复制代码
Vector v=new Vector(10);   
for (int i=1;i<100; i) {   
    Object o=new Object();   
    v.add(o);   
    o=null;   
}   
复制代码

  此时,所有的Object对象都没有被释放,因为变量v引用这些对象。   

   对象加入到Vector后,还必须从Vector中删除,最简单释放方法就是将Vector对象设置为null。   

 

 

 

 

如何检测内存泄露?   

  可以通过一些性能监测分析工具,如 JProfiler、OptimizeitProfiler。

 

 

 

 

 

如何避免内存泄露、内存溢出?

    1)   尽早释放无用对象的引用。

                好的办法是使用临时变量的时候,让引用变量在退出活动域后自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。

         2)   程序进行字符串处理时,尽量避免使用String,而应使用StringBuffer。

               因为每一个String对象都会独立占用内存一块区域,

    如:

String str = "aaa";   
String str2 = "bbb";   
String str3 = str  str2;   

  假如执行此次之后str , str2再不被调用,那么它们就会在内存中等待GC回收;   

  假如程序中存在过多的类似情况就会出现内存错误;   

 

   3)   尽量少用静态变量。

           因为静态变量是全局的,GC不会回收。

         4)  避免集中创建对象尤其是大对象,如果可以的话尽量使用流操作。

         JVM会突然需要大量内存,这时会触发GC优化系统内存环境;

 

    5)  尽量运用对象池技术以提高系统性能。

           生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。

         6)  不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。

           可以适当的使用hashtable,vector创建一组对象容器,然后从容器中去取那些对象,而不用每次new之后又丢弃。

        7)   优化配置。



本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/7622138.html,如需转载请自行联系原作者

相关文章
|
2月前
|
Web App开发 缓存 监控
内存溢出与内存泄漏:解析与解决方案
本文深入解析内存溢出与内存泄漏的区别及成因,结合Java代码示例展示典型问题场景,剖析静态集合滥用、资源未释放等常见原因,并提供使用分析工具、优化内存配置、分批处理数据等实用解决方案,助力提升程序稳定性与性能。
645 1
|
4月前
|
Java 测试技术
Java浮点类型详解:使用与区别
Java中的浮点类型主要包括float和double,它们在内存占用、精度范围和使用场景上有显著差异。float占用4字节,提供约6-7位有效数字;double占用8字节,提供约15-16位有效数字。float适合内存敏感或精度要求不高的场景,而double精度更高,是Java默认的浮点类型,推荐在大多数情况下使用。两者都存在精度限制,不能用于需要精确计算的金融领域。比较浮点数时应使用误差范围或BigDecimal类。科学计算和工程计算通常使用double,而金融计算应使用BigDecimal。
1742 102
|
5月前
|
存储 缓存 人工智能
Java int和Integer的区别
本文介绍了Java中int与Integer的区别及==与equals的比较机制。Integer是int的包装类,支持null值。使用==比较时,int直接比较数值,而Integer比较对象地址;在-128至127范围内的Integer值可缓存,超出该范围或使用new创建时则返回不同对象。equals方法则始终比较实际数值。
178 0
|
3月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
420 1
|
5月前
|
安全 算法 Java
Java 中 synchronized 与 AtomicInteger 的区别
在Java多线程编程中,`synchronized`和`AtomicInteger`均用于实现线程安全,但原理与适用场景不同。`synchronized`是基于对象锁的同步机制,适用于复杂逻辑和多变量同步,如银行转账;而`AtomicInteger`采用CAS算法,适合单一变量的原子操作,例如计数器更新。二者各有优劣,应根据具体需求选择使用。
166 0
|
6月前
|
算法 Java 数据库连接
Java 与 C++ 区别深入剖析及应用实例详解
本文深入剖析了Java和C++两种编程语言的区别,从编译与执行机制、面向对象特性、数据类型与变量、内存管理、异常处理等方面进行对比,并结合游戏开发、企业级应用开发、操作系统与嵌入式开发等实际场景分析其特点。Java以跨平台性强、自动内存管理著称,适合企业级应用;C++则因高性能和对硬件的直接访问能力,在游戏引擎和嵌入式系统中占据优势。开发者可根据项目需求选择合适语言,提升开发效率与软件质量。附面试资料链接:[点此获取](https://pan.quark.cn/s/4459235fee85)。
551 0
|
5月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
1786 0
|
5月前
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
515 1
|
5月前
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
469 0

热门文章

最新文章