发新话题
打印

JAVA垃圾回收机制与内存泄露问题

JAVA垃圾回收机制与内存泄露问题

1.垃圾搜集算法的中心思想
  Java言语树立了垃圾搜集机制, 用以跟踪正在运用的对象和发现并回收不再运用(引用)的对象。 该机制可以有效防备动态内存分配中能够发作的两个危险:因内存垃圾过多而引发的内存耗尽??约安磺〉钡哪诖媸头潘?纬傻哪诖婧戏ㄒ?谩?
  垃圾搜集算法的中心思想是:对虚拟机可用内存空间, 即堆空间中的对象停止辨认, 如果对象正在被引用, 那么称其为存活对象, 反之, 如果对象不再被引用, 则为垃圾对象, 可以回收其占据的空间, 用于再分配。 垃圾搜集算法的选择和垃圾搜集零碎参数的合理调理直接影响着零碎性能, 因此需要开发人员做比拟深入的了解。
  2.触发主GC(Garbage Collector)的条件
  JVM停止次GC的频率很高, 但因为这种GC占用时间极短, 所以对零碎发生的影响不大。 更值得关注的是主GC的触发条件, 因为它对零碎影响很明显。 总的来说, 有两个条件会触发主GC:
  ①当应用程序闲暇时, 即没有应用线程在运转时, GC会被调用。 因为GC在优先级最低的线程中停止, 所以当应用忙时, GC线程就不会被调用, 但以下条件除外。
  ②Java堆内存缺乏时, GC会被调用。 当应用线程在运转, 并在运转进程中创建新对象, 若这时内存空间缺乏, JVM就会强迫地调用GC线程, 以便回收内存用于新的分配。 若GC一次之后仍不能满足内存分配的要求, JVM会再停止两次GC作进一步的尝试, 若仍无法满足要求, 则 JVM将报“out of memory”的错误, Java应用将停止。
  由于是否停止主GC由JVM根据零碎环境决议, 而零碎环境在不时的变化当中, 所以主GC的运转具有不确定性, 无法预计它何时肯定出现, 但可以确定的是对一个临时运转的应用来说, 其主GC是重复停止的。
  3.增加GC开支的措施
  根据上述GC的机制, 程序的运转会直接影响零碎环境的变化, 从而影响GC的触发。 若不针对GC的特点停止设计和编码, 就会出现内存驻留等一系列负面影响。 为了避免这些影响, 基本的原则就是尽能够地增加垃圾和增加GC进程中的开支。 具体措施包括以下几个方面:
  (1)不要显式调用System. gc()
  此函数建议JVM停止主GC, 虽然只是建议而非一定, 但很多情况下它会触发主GC, 从而增加主GC的频率, 也即增加了间歇性停顿的次数。
  (2)尽量增加暂时对象的运用
  暂时对象在跳出函数调用后, 会成为垃圾, 少用暂时变量就相当于增加了垃圾的发生, 从而延伸了出现上述第二个触发条件出现的时间, 增加了主GC的时机。
  (3)对象不用时最好显式置为Null
  普通而言, 为Null的对象都会被作为垃圾处置, 所以将不用的对象显式地设为Null, 有利于GC搜集器判定垃圾, 从而提高了GC的效率。
  (4)尽量运用StringBuffer, 而不用String来累加字符串(详见blog另一篇文章JAVA中String与StringBuffer)
  由于String是固定长的字符串对象, 累加String对象时, 并非在一个String对象中扩增, 而是重新创建新的String对象, 如Str5=Str1+Str2+Str3+Str4, 这条语句执行进程中会发生多个垃圾对象, 因为对次作“+”操作时都必须创建新的String对象, 但这些过渡对象对零碎来说是没有实际意义的, 只会增加更多的垃圾。 避免这种情况可以改用StringBuffer来累加字符串, 因StringBuffer是可变长的, 它在原有基础上停止扩增, 不会发生中间对象。
  (5)能用基本类型如Int, Long, 就不用Integer, Long对象
  基本类型变量占用的内存资源比相应对象占用的少得多, 如果没有必要, 最好运用基本变量。
  (6)尽量少用静态对象变量
  静态变量属于全局变量, 不会被GC回收, 它们会不时占用内存。
  (7)分散对象创建或删除的时间
  集中在短时间内少量创建新对象, 特别是大对象, 会招致突然需要少量内存, JVM在面临这种情况时, 只能停止主GC, 以回收内存或整合内存碎片, 从而增加主GC的频率。 集中删除对象, 道理也是一样的。 它使得突然出现了少量的垃圾对象, 闲暇空间肯定增加, 从而大大增加了下一次创建新对象时强迫主GC的时机。
  4.gc与finalize方法
  ⑴gc方法恳求垃圾回收
  运用System. gc()可以不管JVM运用的是哪一种垃圾回收的算法, 都可以恳求Java的垃圾回收。 需要留意的是, 调用System. gc()也仅仅是一个恳求。 JVM接受这个消息后, 并不是立刻做垃圾回收, 而只是对几个垃圾回收算法做了加权, 使垃圾回出操作容易发作, 或延迟发作, 或回收较多而已。
  ⑵finalize方法透视垃圾搜集器的运转
  在JVM垃圾搜集器搜集一个对象之前 , 普通要求程序调用适当的方法释放资源, 但在没有明白释放资源的情况下, Java提供了缺省机制来终止化该对象释放资源, 这个方法就是finalize()。 它的原型为:
  protected void finalize() throws Throwable
  在finalize()方法前往之后, 对象消逝, 垃圾搜集开端执行。 原型中的throws Throwable表示它可以抛出任何类型的异常。
  因此, 当对象即将被销毁时, 有时需要做一些善后任务。 可以把这些操作写在finalize()方法里。
  protected void finalize()
  {
  // finalization code here
  }
  ⑶代码示例
  class Garbage
  {
  int index;
  static int count;
  Garbage()
  {
  count++;
  System. out. println("object "+count+" construct");
  setID(count);
  }
  void setID(int id)
  {
  index=id;
  }
  protected void finalize() //重写finalize方法
  {
  System. out. println("object "+index+" is reclaimed");
  }
  public static void main(String[] args)
  {
  new Garbage();
  new Garbage();
  new Garbage();
  new Garbage();
  System.gc(); //恳求运转垃圾搜集器
  }
  }文章由Gainreel内衣旗舰店整理,收集辛苦,希望能保留出处。
jiyizhen-buy.com颈椎保健枕太空记忆枕 igerl.com歌瑞尔内衣

TOP

发新话题