`
我改名了
  • 浏览: 89231 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

java 内存溢出

    博客分类:
  • OOM
 
阅读更多

Java也会内存泄露吗?  读书的时候,都说Java自动管理内存,JVM内涵GC机制,只管用不管释放,JVM自动会回收内存,不会存在内存泄露.

  不过经过多年C&C++编程,一直尚未接触Java,也不知道Java是否真的永远不会内存泄露.....,抱着怀疑的精神,我一直疑问不敢实战求证,因为我不会Java,为什么怀疑呢?因为JVM无非还是用C&C++实现的,咋就不会内存泄露呢?C++都要内存泄露,Java这种字节码还需要翻译的运行在JVM内的语言就不会内存泄露?当然我承认,我当时的理解还停留在原生态....

  多年之后,再来接触Java,发现我被欺骗了....

  Java真的不会内存泄露吗?

  面试过很多人,问他们曾经是否写有过Java内存泄露的代码,无一回答曾有.而真正实战代码的时候,我却发现,他们都写着一堆疑似内存泄露的代码,或许我被欺骗,或许他们的代码没有经过日夜煎熬奋战在最前线,每天享受着500以上的并发处理吧.

  从不少同学,同事口里得知,其实Java会"内存泄露",曾经有个同事说,X组做的J2EE应用服务,就像定时炸 弹,一天重启七八次....为什么重启呢?因为内存泄露.

  自己也做了J2EE应用服务,虽然没有达到一天重启七八次,也有两三天一次,高峰的时候一天两次.为什么呢?因为内存泄露...

  此处,我阐述一下我对内存泄露的理解,内存泄露一般大家都认为是C和C++中new出一块内存,然后没有释放delete,这块内存就造成了内存泄露.其实我也是这么理解的,不过我更觉得,一块内存如果被申请,存放了一堆废弃的数据,而且内存一直这样占据下去,我觉得也是一种内存泄露.当然更恐怖的就是这样占据的内存在一个程序的关键点使用造成不停的增大,就等待crash吧...

  所以在我眼中,Java的内存泄露与C++的内存泄露没什么区别,一个是GC可达却无法去释放,一个是人为没有delete,这两种情况都是一块内存没有在可delete的范围之内,当然有人说,Java的任何对象是可达的连通图,C++的内存是没有任何对象handle了此内存.Java更安全一些,可是我想说,Java就像一张被银行印有伪钞二字的RMB,C++就像一个分钱没有的穷光蛋,其实大家都是一无所有.大家都是内存泄露...

  从理论上讲,Java内存泄露的范围更小但是我觉得她更危险!为什么?有这么一个习惯,大多时候,让错误ERROR尽量的暴露出来而不是隐藏下去继续执行...

  GC机制没有一个标准,那是一个算法,各个JVM的GC机制不一样,算法不一样,只要算法有漏洞,你的程序可能存在内存泄露,金无足赤,所以不要期待有完美的算法,同样的代码使用不同的JVM,极端情况下,有一个JVM就可能内存泄露,而另外一个JVM可能不会内存泄露.越说越玄乎....其实不要那么担心,编写JVM的都是世界达人,我们要相信比我们聪明的达人.

  废话不多说,说说最近两次解决的系统内存泄露问题.

  上面说过,Java内存泄露与JVM的GC算法机制有关系,网上经常有人举Java内存泄露的代码,如:

  List<Object> list = new ArrayList<Object>

  for(int i=0;i<10;i++){

    Objet a = new Object();

    list.add(a);

  }

  网上对这句话的解释太多了,new Object发生了内存泄露,其实我脑袋被铁打了,我根本看不出new Object怎么内存泄露了,因为new Object被list对象hold住了,list没有释放,尽管a释放了,但是还是内存泄露了.........这个我怎么说好呢,这个叫断章取义吧,那list释放了Object也就被释放了嘛,那也就是说list永远不释放的时候才会造成Object的内存泄露啊,我想知道我们在什么时候不会对list做释放?

  大家都很聪明,我们声明list为static变量的时候,list就永远不会释放啦,但我很想知道大家是在写程序还是在做辩论会?既然你声明list为全局static变量,那么必定是想让Object被hold住,被全局用起来,做一个缓存作用.如果你不是此意,你为什么要用static变量?如果是这样还是回家看看ABC吧.

  所以如果你书写上面的如此代码是不会造成内存泄露的,除非你声明为static,并且将此段代码在程序中反复调用.除非是故意,否则我想中国程序员还没有达到故意制造内存泄露的境界.

  而我第一次解决内存泄露,应该归纳为"内存碎片",因为零星的内存碎片(其实是很小的Java对象)存在于JVM的内存池中[不清楚JVM的内存池是对象内存池还是原生内存池],无论哪种情况,都是因为很小的内存对象被new出来,存在于JVM内存池的各个角落,造成JVM不断GC,GC的过程中内存碎片又总是被hold住无法释放,随着时间的推移,当接近heap峰值的时候,JVM因为GC而直接crash...

  一般内存碎片是因为不当的编码,将零星无用对象秒存在了某个长生命周期对象当中被持有必须等待父对象释放才能释放"内存碎片",我遇见的内存碎片是在action当中对List成员直接进行new空数组,然后再将List对象指向来自hibernate的对象数组.造成new出来的数组对象成为内存碎片.如果下面的代码:

List list = new ArrayList();

list = listOther; // listOther是来自hibernate返回的数据库PO对象列表

  不是new ArrayList不会释放,而是他释放的时机与JVM的GC机制形成了对抗,服务器采用的是Weblogic & SUN JDK1.6至于其他JVM就不太清楚是否也会这样.

  第二次内存泄露更疯狂,一天重启两次服务器,有了第一次内存泄露的经验,此次内存泄露解决时间大大缩短到了一个星期以内.第二次是CXF的webservice与quartz定时器相结合的时候,在设置webservice的HttpClientPolicy权限时,声明了一个静态常量static HttpClientPolicy作为webservice的公共权限,因为webservice内部编码机制,让HttpClientPolicy反引用了WebService的Client,造成内存无法释放.并且在WebService中加入了listener,没有对listener进行清理.加上quartz定时器破坏了Sprin的引用规则,多种原因错综复杂搅在一起造成大量hold内存对象.所以提个醒,Java引用复杂,不要轻易声明static变量,不要认为是别人hold住你,而不是你hold住别人,因为在你没有明确编码内部算法的时候,大家都有有可能互相hold

 

 

本文转自:http://hi.baidu.com/crazyonline/item/cc01a883201ebccdee083d76

分享到:
评论
2 楼 我改名了 2013-04-11  
个人感觉本文 关于 内存碎片 的说法是不准确甚至是错误的 。而关于内存泄漏方面讲的过于浅陋 。
1 楼 我改名了 2013-04-11  
我很悲剧,发个博客, 连炸 弹两个字都不让发。难道也要实行文字狱吗? 害我要再炸 弹中间加个空格

相关推荐

    JAVA内存溢出

    JAVA内存溢出 JAVA中OutOfMemoryError(内存溢出)的三种情况及解决办法 Java中的OutOfMemoryError(内存溢出)是一种常见的错误,本文将详细介绍OutOfMemoryError的三种情况及其解决方法。 首先,我们需要了解...

    JAVA内存溢出详解.doc

    Java内存溢出(Out Of Memory,OOM)是Java应用程序运行时常见的问题,它通常发生在程序对内存需求超过了Java虚拟机(JVM)所能提供的可用内存时。本文将深入探讨Java内存溢出的原因、表现以及如何解决。 1. **Java...

    java 内存溢出分析工具 HeapAnalyzer

    Java内存溢出(Out of Memory,OOM)是Java应用程序中常见的问题,会导致程序崩溃或性能急剧下降。HeapAnalyzer是一款强大的工具,专为分析Java应用程序的内存状况,特别是针对内存溢出问题进行诊断。本文将详细介绍...

    JAVA内存溢出问题总结

    JAVA内存溢出问题总结 JAVA 内存溢出问题是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用的内存大于虚拟机能提供的最大内存。内存溢出问题可以从容器和程序类两个方面进行排查,容器问题...

    Java内存溢出解决办法

    Java内存溢出问题,全称为Java OutOfMemoryError,是Java开发者经常遇到的运行时异常。内存溢出通常发生在程序运行过程中,系统无法为运行的应用程序分配足够的内存资源,导致程序无法正常执行。理解并解决Java内存...

    【Java面试题】Java内存溢出

    【Java面试题】Java内存溢出

    java内存溢出解决方案

    Java内存溢出问题通常指的是Java应用程序在运行过程中由于内存分配不当或使用过度导致JVM无法分配更多的内存,从而抛出`java.lang.OutOfMemoryError`异常。本文将深入探讨Java内存溢出的不同类型及其解决方案。 1. ...

    Java 内存溢出解决办法

    Java内存溢出问题通常指的是程序在试图分配内存时,无法找到足够的连续内存空间而抛出的异常。在Java中,内存分为几个区域:堆(Heap)、栈(Stack)、方法区(Method Area,Java 8后被元空间取代)以及程序计数器和...

    Java内存溢出的详细解决方案

    Java内存溢出的详细解决方案 Java内存溢出是指Java虚拟机(JVM)中的内存使用超过了最大限制,导致程序崩溃或无法正常运行的错误。Java内存溢出主要有两种类型:PermGen space和Java heap space。 PermGen space ...

    基于HeapAnalyzer456.jar 分析java内存溢出

    HeapAnalyzer456.jar 是一个专门用于分析Java内存溢出的专业工具,它可以帮助开发者深入理解内存的分配、使用和泄漏状况。本篇文章将详细介绍如何使用HeapAnalyzer456.jar来分析Java内存溢出问题。 首先,我们需要...

    java内存溢出原因

    Java内存溢出(Out Of Memory, OOM)是开发者在编程过程中经常遇到的问题,尤其是在处理大量数据或长时间运行的应用程序时。本篇文章将详细解析三种常见的Java内存溢出类型:JVM PermGen space溢出、JVM heap space...

    JRockit JAVA内存溢出检测的使用(CHM)

    **JRockit JAVA内存溢出检测的使用** Java内存溢出是开发和运行Java应用程序时常见的问题,可能导致程序崩溃或性能急剧下降。JRockit JVM(Java Virtual Machine)由Oracle公司开发,它提供了强大的内存管理和分析...

    Java内存溢出

    Java内存溢出的知识点 Java内存溢出是指Java虚拟机(JVM)在执行过程中无法分配对象所需的内存,导致程序崩溃或无法继续运行的错误。Java内存溢出类型有多种,下面将详细介绍其中的四种类型。 1. java.lang....

    解决JAVA内存溢出问题

    在探讨如何解决JAVA内存溢出问题时,我们首先需要理解几个关键的概念,包括JVM(Java虚拟机)、Tomcat服务器、以及与之相关的内存参数设置。本文将详细解析标题及描述中提到的知识点,帮助读者深入理解JAVA内存管理...

    Java内存溢出和内存泄露共4页.pdf.zip

    解决Java内存溢出和内存泄露的方法主要包括以下几点: 1. 适当调整JVM参数:通过设置-Xms和-Xmx指定堆内存的初始大小和最大大小,避免因动态扩展导致的溢出。同时,可以通过-Xss设置线程栈的大小,防止栈溢出。 2....

    关于static的小结(Java内存溢出)

    ### 关于static的小结(Java内存溢出) #### 标题和描述中的知识点 在《关于static的小结(Java内存溢出)》这篇文章中,作者主要探讨了与Java中的`static`关键字相关的知识点,以及如何可能导致内存溢出的情况。...

    Java内存溢出问题

    Java内存溢出问题,是Java开发中常见的性能问题,它发生在程序运行时,由于系统无法分配足够的内存资源来满足程序的运行需求,导致程序异常终止。深入理解Java内存溢出,有助于我们优化程序,提高系统稳定性。下面...

    java 内存溢出分析工具 CoreAnalyzer

    Java内存溢出(Out of Memory, OOM)是开发者在编程过程中经常遇到的问题,尤其是在处理大量数据或长时间运行的应用程序时。为了解决这一问题,Java提供了多种内存分析工具,其中CoreAnalyzer是一款专业的Java内存...

    java内存泄露、溢出检查方法和工具

    Java内存管理是开发Java应用程序时的关键环节,内存泄露和溢出问题可能导致系统性能下降,甚至导致服务崩溃。本文将深入探讨如何检测和分析Java内存泄露与溢出,并介绍一种常用的工具——Memory Analyzer(MAT)。 ...

Global site tag (gtag.js) - Google Analytics