会计考友 发表于 2012-8-4 12:28:23

java认证:Java中的必须执行清除情况简介

为断根一个对象,阿谁对象的用户必需在但愿进行断根的地址挪用一个断根体例。这听起来似乎很轻易做到,但饶暌闺C++“破损器”的概念稍有抵触。在C++中,所有对象城市破损。若但愿执行除释放存储空间之外的其他某种形式的断根工作,仍然必需挪用Java中的一个体例。它等价于C++的破损器,只是没后者便利。
  finalize()最有用处的处所之一是不雅察看垃收受接管集的过程。下面这个例子向巨匠展示了垃收受接管集所履历的过程,并对前面的陈述进行了总结。//: Garbage.java
  // Demonstration of the garbage
  // collector and finalizationclass Chair {
  static boolean gcrun = false;
  static boolean f = false;
  static int created = 0;
  static int finalized = 0;
  int i;
  Chair() {
  i = ++created;
  if(created == 47)
  System.out.println("Created 47");
  }
  protected void finalize() {
  if(!gcrun) {
  gcrun = true;
  System.out.println(
  "Beginning to finalize after " +
  created + " Chairs have been created");
  }
  if(i == 47) {
  System.out.println(
  "Finalizing Chair #47, " +
  "Setting flag to stop Chair creation");
  f = true;
  }
  finalized++;
  if(finalized >= created)
  System.out.println(
  "All " + finalized + " finalized");
  }
  }public class Garbage {
  public static void main(String[] args) {
  if(args.length == 0) {
  System.err.println("Usage: n" +
  "java Garbage beforenor:n" +
  "java Garbage after");
  return;
  }
  while(!Chair.f) {
  new Chair();
  new String("To take up space");
  }
  System.out.println(
  "After all Chairs have been created:n" +
  "total created = " + Chair.created +
  ", total finalized = " + Chair.finalized);
  if(args.equals("before")) {
  System.out.println("gc():");
  System.gc();
  System.out.println("runFinalization():");
  System.runFinalization();
  }
  System.out.println("bye!");
  if(args.equals("after"))
  System.runFinalizersOnExit(true);

会计考友 发表于 2012-8-4 12:28:24

java认证:Java中的必须执行清除情况简介

  }
  } ///:~膳缦沔这个轨范建树了良多Chair对象,而且在垃收受接管集器起头运行后的某些时辰,轨范会遏制建树Chair。因为垃收受接管集器可能在任何时刻运行,所以我们不能切确知道它在何时启动。是以,轨范用一个名为gcrun的标识表记标帜来指出垃收受接管集器是否已经起头运行。操作第二个标识表记标帜f,Chair可告诉main()它应遏制对象的生成。这两个标识表记标帜都是在finalize()内部设置的,它挪用于垃收受接管集时代。
  另两个static变量——created以及finalized——分袂用于跟踪已建树的对象数目以及垃收受接管集器已进行完收尾工作的对象数目。最后,每个Chair都有它自己的(非static)int i,所以能跟踪体味它具体的编号是若干好多。编号为47的Chair进行完收尾工作后,标识表记标帜会设为true,最终竣事Chair对象的建树过程。
  所有这些都在main()的内部进行——不才面这个轮回里:while(!Chair.f) {
  new Chair();
  new String("To take up space");
  }巨匠可能会迷惑这个轮回什么时辰会停下来,因为内部没有任何改变Chair.f值的语句。然而,finalize()历程会改蹦这个值,直至最终对编号47的对象进行收尾措置。
  每次轮回过程中建树的String对象只是属于额外的垃圾,用于吸引垃收受接管集器——一旦垃收受接管集器对可用内存的容量感应“严重不安”,就会起头关注它。
  运行这个轨范的时辰,供给了一个呼吁行自变量“before”或者“after”。此鱿脯“before”自变量会挪用System.gc()体例(强制执行垃收受接管集器),同时还会挪用System.runFinalization()体例,以便进行收尾工作。这些体例都可在Java 1.0中使用,但经由过程使用“after”自变量而挪用的runFinalizersOnExit()体例却只有Java 1.1及后续版本供给了对它的撑持(注释③)。注重可在轨范执行的任何时辰挪用这个体例,而且收尾轨范的执行与垃收受接管集器是否运行是无关的。③:不幸的是,Java 1.0采用的垃收受接管集器方案永远不能正确地挪用finalize()。是以,finalize()体例(出格是那些用于封锁文件的)事实上经常都不会获得挪用。此刻有些文章声称所有收尾囊臻城市在轨范退出的时辰获得挪用——即使到轨范中止的时辰,垃收受接管集器仍未针对那些对象采纳步履。这并不是真实的情形,所以我们根柢不能指望finalize()能为所有对象而挪用。出格地,finalize()在Java 1.0里几乎毫无用处。前面的轨范向我们揭示出:在Java 1.1中,收尾囊臻必定会运行这一允诺已成为现实——但前提是我们明晰地强制它采纳这一操作。若使用一个不是“before”或“after”的自变量(如“none”),那么两个收尾工作都不会进行,而且我们会获得象下面这样的输出:
  Created 47
  Created 47
  Beginning to finalize after 8694 Chairs have been created
  Finalizing Chair #47, Setting flag to stop Chair creation
  After all Chairs have been created:
  total created = 9834, total finalized = 108
  bye!是以,到轨范竣事的时辰,并非所有收尾囊臻城市获得挪用。为强制进行收尾工作,可先挪用System.gc(),再挪用System.runFinalization()。这样可断根到今朝为止没有使用的所有对象。这样做一个稍显奇异的处所是在挪用runFinalization()之前挪用gc(),这看起来似乎与Sun公司的文档声名有些抵触,它传布鼓吹首先运行收尾囊臻,再释放存储空间。然而,若在这里首先挪用runFinalization(),再挪用gc(),收尾囊臻根柢不会执行。针对所有对象,Java 1.1有时之所以会默认为跳过收尾工作,是因为它认为这样做的开销太年夜。不管用哪种体例强制进行垃收受接管集,都可能注重到比没有额外收尾工壮杀鞠长的时刻延迟。
页: [1]
查看完整版本: java认证:Java中的必须执行清除情况简介