Java内存溢出-2

上一篇 / 下一篇  2012-06-11 09:39:47 / 个人分类:Java

为了避免这些问题,程序的设计和编写就应避免垃圾对象的内存占用和 GC 的开销。显示调用 System.GC() 只能建议 JVM 需要在内存中对垃圾对象进行回收,但不是必须马上回收,

&TU_R_"J&E0  一个是并不能解决内存资源耗空的局面,另外也会增加 GC 的消耗。51Testing软件测试网"vX%A,K.nD r

51Testing软件测试网U(x7aQ Q1Cia}

  二、 JVM 内存区域组成

5T0f$b'f!P.mrC!N051Testing软件测试网c ZQ.gM^

  简单的说 java中的堆和栈

7Eq/V3F@O1i7L0

Z@;t[W8R0  java把内存分两种:一种是栈内存,另一种是堆内存

W-ax#fZ ZBe0

|*V2J I4p6cR0  1、在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;51Testing软件测试网@hs^#m:b9H4Zx

Xijb zb0  2、堆内存用来存放由 new创建的对象和数组51Testing软件测试网%sX-ffO!|&R~I

51Testing软件测试网rw'b P#[3O

  在函数(代码块)中定义一个变量时, java就在栈中为这个变量分配内存空间,当超过变量的作用域后, java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由 java虚拟机的自动垃圾回收器来管理51Testing软件测试网$Wc%nd/O)Q`,yf

51Testing软件测试网tH$U@.p

  堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;

$m,D},kB:O:{l051Testing软件测试网4f oUu;kH V

  栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活 性。

^ q(N9n,TC:h)cT`t0

+g0[6N9Tb8f[:j0  java 堆分为三个区: New 、 Old 和 Permanent

+i(c@5U w5h6^051Testing软件测试网k0Y'Ht RW#jjG

  GC 有两个线程:

4Hy7w5aZ4L.Cr0

q2r#UC;?/U)W-s0  新创建的对象被分配到 New 区,当该区被填满时会被 GC 辅助线程移到 Old 区,当 Old 区也填满了会触发 GC 主线程遍历堆内存里的所有对象。 Old 区的大小等于 Xmx 减去 -Xmn

.w)Vk&y0](mI/Jt-}0

Id)g:`u0  java栈存放

X+o1QAs051Testing软件测试网 a}3Gj:o5Y

  栈调整:参数有 +UseDefaultStackSize -Xss256K,表示每个线程可申请 256k的栈空间

J*fB.j#G Hv fyT051Testing软件测试网6m}$zF;?YLfm

  每个线程都有他自己的 Stack

J-S(JO`0

G^8|)\%G.xVF-N0  三、JVM如何设置虚拟内存51Testing软件测试网N;Iz:V-`O(];E&s,_]

51Testing软件测试网9_ Bg'Gt

  提示:在 JVM中如果 98%的时间是用于 GC且可用的 Heap size 不足 2%的时候将抛出此异常信息。51Testing软件测试网/Si$^I$H

51Testing软件测试网oKa'K+pG5FD

  提示:Heap Size 最大不要超过可用物理内存的 80%,一般的要将 -Xms和 -Xmx选项设置为相同,而 -Xmn为 1/4的 -Xmx值。51Testing软件测试网oQD&} Q7A8G.m

&qO#LCdU Vur0  提示:JVM初始分配的内存由 -Xms指定,默认是物理内存的 1/64;JVM最大分配的内存由 -Xmx指定,默认是物理内存的 1/4。51Testing软件测试网,i"a}M*_P ex

y n4{)v\X0  默认空余堆内存小于 40%时,JVM就会增大堆直到 -Xmx的最大限制;空余堆内存大于 70%时, JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置 -Xms、-Xmx相等以避免在每次 GC 后调整堆的大小。51Testing软件测试网6[Sui4fk2g[

t1n(B/p0\;Hny6p0  提示:假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。

3YVI6N8S6UVj-{0

S4^y5X daqM0  简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,

4{Q)a,l?.x0

|,R0nY d5A0  这个限制一般是 2GB-3GB(一般来说 Windows系统下为 1.5G-2G, Linux系统下为 2G-3G), 而 64bit以上的处理器就不会有限制了51Testing软件测试网PM+q~.rP

51Testing软件测试网 F{3_"ns&r

  提示:注意:如果 Xms超过了 Xmx值,或者堆最大值和非堆最大值的总和超过了物理内 存或者操作系统的最大限制都会引起服务器启动不起来。

3Ga3@8eW0

`*M!]/Fm `+F([;`:M0  提示:设置 NewSize、 MaxNewSize相等,“new”的大小最好不要大于 “old”的一半,原因是 old区如果不够大会频繁的触发 “主 ” GC ,大大降低了性能

sI6]7veGw rr$k0

CH#nCA&J0  JVM使用 -XX:PermSize设置非堆内存初始值,默认是物理内存的 1/64;

JNH%|)aD0

&A`wR/m9}8Z0  由 XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的 1/4。51Testing软件测试网;]d9W@H8T,W J^I

E-fr1s(m1o0  解决方法:手动设置 Heap size

:p0v h%{^8o D+H?051Testing软件测试网2t0W)c&DzJ*Or5MH y

  修改 TOMCAT_HOME/bin/catalina.bat51Testing软件测试网 b!t5N Q^g3~

51Testing软件测试网"s"qh*?0f

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

4I*j"H _6w,m\0mo0

`(J t@0Vt;e051Testing软件测试网ttt_!S ~

JAVA_OPTS=”-server -Xms800m -Xmx800m -XX:MaxNewSize=256m”
;n wjm u{:u[ h5p0
四、性能检查工具使用

:Ba3B V;vQ0  定位内存泄漏:

7h1w#m(p m7\f8^0

4Rln,P7i,`h0  JProfiler 工具主要用于检查和跟踪系统(限于 Java 开发的)的性能。 JProfiler 可以通过时时的监控系统的内存使用情况,随时监视垃圾回收,线程运行状况等手段,从而很好的监视 JVM 运行情况及其性能。51Testing软件测试网 J|5y3K%y4w

51Testing软件测试网&z+L#V)u2}7kQgU%B

  1、应用服务器内存长期不合理占用,内存经常处于高位占用,很难回收到低位;51Testing软件测试网.aR0t&OcPB?

dyt3V4O*W ]N7s%B0  2、应用服务器极为不稳定,几乎每两天重新启动一次,有时甚至每天重新启动一次;

F1s^-UfkY9C ?0

!|PDf~ B2D!Q0  3、应用服务器经常做 Full GC(Garbage Collection),而且时间很长,大约需要 30-40秒,应用服务器在做 Full GC的时候是不响应客户的交易请求的,非常影响系统性能。51Testing软件测试网:E/Nt$N.w

Yh P eg0  因为开发环境和产品环境会有不同,导致该问题发生有时会在产品环境中发生, 通常可以使用工具跟踪系统的内存使用情况,在有些个别情况下或许某个时刻确实 是使用了大量内存导致 out of memory,这时应继续跟踪看接下来是否会有下降,

}KC]"_$W.W\0

__U A4n u6{j D0  如果一直居高不下这肯定就因为程序的原因导致内存泄漏。51Testing软件测试网 Wp!p4\rL

51Testing软件测试网ofi jM!h*W$l

  五、不健壮代码的特征及解决办法

W z h a9f bT/R051Testing软件测试网1ta9f et1\7q*m

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

(s"q-Z2t)fs0

'pIG!WC-m0  对于仍然有指针指向的实例, jvm 就不会回收该资源 , 因为垃圾回收会将值为 null 的对象作为垃圾,提高 GC 回收机制效率;

PeIuV.G0

c T/fi:E8T)}0  2、我们的程序里不可避免大量使用字符串处理,避免使用 String ,应大量使用 StringBuffer ,每一个 String 对象都得独立占用内存一块区域;

"?i1ArY051Testing软件测试网*B#j;Y7Vs eq,L:D;JU,V9k

6W+D5j,x2s4k a2v0Z0
  1. String str = “aaa”;   
  2.   
  3. String str2 = “bbb”;   
  4.   
  5. String str3 = str + str2;// 假如执行此次之后 str ,str2 以后再不被调用 , 那它就会被放在内存中等待 Java 的 gc 去回收 , 程序内过多的出现这样的情况就会报上面的那个错误 , 建议在使用字符串时能使用 StringBuffer 就不要用 String, 这样可以省不少开销;
51Testing软件测试网(b;Q$h6~F&R[

  3、尽量少用静态变量,因为静态变量是全局的, GC 不会回收的;

]0us*i5bb,{#V051Testing软件测试网(c;^{ RmN-Bx2c#ER.\6X

  4、避免集中创建对象尤其是大对象, JVM 会突然需要大量内存,这时必然会触发 GC 优化系统内存环境;显示的声明数组空间,而且申请数量还极大。

A } TZ6b!e h,]T0

djuea bf0  这是一个案例想定供大家警戒:51Testing软件测试网 PSz#{0fY

Uw f3j L Vr3Ox!Dw0  使用jspsmartUpload作文件上传,现在运行过程中经常出现java.outofMemoryError的错误,用top命令看看进程使用情况,发现内存不足2M,花了很长时间,发现是jspsmartupload的问题。把jspsmartupload组件的源码文件(class文件)反编译成Java文件,如梦方醒:

6\:vK{6yzc#`051Testing软件测试网b`X o$G#|ia~

5_ R P b+`by0
  1. m_totalBytes = m_request.getContentLength();        
  2. m_binArray = new byte[m_totalBytes];
变量m_totalBytes表示用户上传的文件的总长度,这是一个很大的数。如果用这样大的数去声明一个byte数组,并给数组的每个元素分配内存空间,而且m_binArray数组不能马上被释放,JVM的垃圾回收确实有问题,导致的结果就是内存溢出。

D OfQ8S C` e,jv0  jspsmartUpload为什末要这样作,有他的原因,根据RFC1867的http上传标准,得到一个文件流,并不知道文件流的长度。设计者如果想文件的长度,只有操作servletinputstream一次才知道,因为任何流都不知道大小。只有知道文件长度了,才可以限制用户上传文件的长度。为了省去这个麻烦,jspsmartUpload设计者直接在内存中打开文件,判断长度是否符合标准,符合就写到服务器的硬盘。这样产生内存溢出,这只是我的一个猜测而已。51Testing软件测试网c2D:T#z y0xm8?.q"e

51Testing软件测试网g!YBE@(Z4W

  所以编程的时候,不要在内存中申请大的空间,因为web服务器的内存有限,并且尽可能的使用流操作,例如

7RI9n?gR051Testing软件测试网%~YD#Q.fbU

I F V/YH3r0
  1. byte[] mFileBody = new byte[512];   
  2.          Blob vField= rs.getBlob("FileBody");   
  3.       InputStream instream=vField.getBinaryStream();   
  4.       FileOutputStream fos=new FileOutputStream(saveFilePath+CFILENAME);   
  5.          int b;   
  6.                       while( (b =instream.read(mFileBody)) != -1){   
  7.                         fos.write(mFileBody,0,b);   
  8.                          }   
  9.         fos.close();   
  10.       instream.close();

uPMU{%s[2Ep0  5、尽量运用对象池技术以提高系统性能;生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。51Testing软件测试网#XN,Q'f8v ^.?5_5}i:[

~L M3Vk.q`%b0  6、不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。可以适当的使用 hashtable , vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次 new 之后又丢弃

-Y,Htn'T!u\J051Testing软件测试网[ pD(zs0VU,P

  7、一般都是发生在开启大型文件或跟数据库一次拿了太多的数据,造成 Out Of Memory Error 的状况,这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。

2L1{n4bq0

TAG:

 

评分:0

我来说两句

Open Toolbar