a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 72|回复: 0

[其他] JAVA技巧:Java内存泄露问题分析

[复制链接]
发表于 2012-8-4 12:28:23 | 显示全部楼层 |阅读模式
良多人在谈论内存泄露问题,当然对于c/c++来说,这个应该是老失踪牙的问题,可是良多Java人员也越来越多得谈判这个问题,我这里写个小结,但愿对巨匠有必然的参考价值。   内存泄露的慨念, a8 ~' t/ j. F1 v; g
  1.c/c++是轨范员自己治理内存,Java内存是由GC自动收受接管的。, k, G' T, R  }  O4 N
  我虽然不是很熟悉C++,不外这个应该没有犯常识性错误吧。4 x" f) w8 X7 L/ W) ^4 `
  2.什么是内存泄露?. h+ U3 t' C9 e3 K8 p, R+ l
  内存泄露是指系统中存在无术数受接管的内存,有时辰会造成内存不足或系统解体。3 j. F' o' _# n! i
  在C/C++平分配了内存不释放的情形就是内存泄露。
5 N8 B# |- P) h# }& X  3.Java存在内存泄露
$ }4 j! B1 G7 p0 A/ }: \  我们必需先认可这个,才可以接着谈判。虽然Java存在内存泄露,可是根基上不用很关心它,不凡是那些对代码自己就不讲究的就更不要去关心这个了。
- t( q: n! _0 ]/ W6 k  e) Q1 @  Java中的内存泄露当然是指:存在无用可是垃圾收受接管器无术数受接管的对象。而且即使有内存泄露问题存在,也不必然会默示出来。: H4 V' t2 y2 f0 ~. C6 U( E
  4.Java中参数都是传值的。7 U0 l  X" ?4 z8 x4 A& x" A
  对于根基类型,巨匠根基膳缦慊有讲话,可是对于引用类型我们也不能有讲话。
4 P' M4 o  t: p+ T& {- d  Java是若何打点内存
" o3 Q! K. _2 J2 i. ~; R( Y  为了判定Java中是否有内存泄露,我们首先必需体味Java是若何打点内存的。Java的内存打点就是对象的分配和释放问题。在Java中,轨范员需要经由过程关头字new为每个对象申请内存空间 (根基类型除外),所有的对象都在堆 (Heap)平分配空间。此外,对象邓晔着是由GC抉择和执行的。在Java中,内存的分配是由轨范完成的,而内存邓晔着是有GC完成的,这种收支两条线的体例确实简化了轨范员的工作。但同时,它也加重了JVM的工作。这也是Java轨范运行速度较慢的原因之一。因为,GC为了能够正确释放对象,GC必需监控每一个对象的运行状况,搜罗对象的申请、引用、被引用、赋值等,GC都需要进行监控。
: z6 c8 ]8 k" x8 m  看管对象状况是为了加倍切确地、实时地释放对象,而释放对象的根柢原则就是该对象不再被引用。
. V( p# S# t! }: e  为了更好理解GC的工作事理,我们可以将对象考虑为有向图的极点,将引用关系考虑为图的有向边,有向边年夜引用者指向被引对象。此外,每个线程对象可以作为一个图的肇端极点,例如年夜多轨范年夜main历程起头执行,那么该图就是以main历程极点起头的一棵根树。在这个有向图中,根极点可达的对象都是有用对象,GC将不收受接管这些对象。如不美观某个对象 (连通子图)与这个根极点不成达(注重,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC收受接管。9 X7 q' D3 ~$ x. x7 {- V
  以下,我们举一个例子声名若何用有向图暗示内存打点。对于轨范的每一个时刻,我们都有一个有向图暗示JVM的内存分配情形。以下右图,就是左边轨范运行到第6行的示意图。
* Y$ f* }3 `7 w+ o  Q# p3 }8 x) S6 m/ L, C* U' Z( F
  Java使用有向图的体例进行内存打点,可以消弭引用轮回的问题,例若有三个对象,彼此引用,只要它们和根历程不成达的,那么GC也是可以收受接管它们的。这种体例的利益是打点内存的精度很高,可是效率较低。此外一种常用的内存打点手艺是使用计数器,例如COM模子采用计数器体例打点构件,它与有向图对比,精度行低(很难措置轮回引用的问题),但执行效率很高。( ?' W) S9 [: S* X! f
  Java内存泄露情形
7 o. N, T5 H) K- J) ?4 f  JVM收受接管算法是很复杂的,我也不知道他们怎么实现的,可是我只知道他们要实现的就是:对于没有被引用的对象是可以收受接管的。所以你要造成内存泄露就要做到:
8 R# ]7 p$ Z% A% W6 n  持有对无用对象的引用!
1 g) ], s6 w/ w6 u4 B, Q+ m) N  不要觉得这个很等闲做到,既然无用,你怎么还会持有它的引用? 既然你还持有它,它怎么会是无用的呢?
0 B2 V' A( A8 `  我其实想不到比阿谁仓库更经典的例子了,甚至于我还要引用别人的例子,下面的例子不是我想到的,是书上看到的,当然假如没有在书上看到,可能过一段时刻我自己也想的到,可是那时我说是我自己想到的也没有人相信的。
0 }8 H% n0 J" @6 R8 S  i+ h' [  public class Stack {6 o2 {' \) ~* D
  private Object[] elements=new Object[10];
# Q2 b# Z3 @4 q; x* T7 t% H" v0 D. ?+ G  private int size = 0;  X& w+ ]5 L9 L% C: Y
  public void push(Object e){
( R9 c3 X5 \2 S. p2 N  ensureCapacity();/ d1 B) J# e$ ~" |) J% t( B
  elements[size++] = e;8 B  G) m& H4 f
  }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-21 20:45 , Processed in 0.221017 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表