The Secret life of the Finalizer__java

Source: Internet
Author: User

find a good article, talk about the life cycle of finalizer, good articles must be transferred: http://www.fasterj.com/articles/finalizer1.shtml


in this article, Jack Shirazi looks to exactly what the JVM doeswhen you create a Finalizable object and then I T garbagecollected. And it is surprisingly bizarre in times. Published November 2007, Author Jack Shirazi

Page 1 of 2
Next page:the Finalizer lifecycle

In this article, I ' m going to have a look into exactly what the JVM doeswhen you create a Finalizable object, following it s lifecycle through until it gets garbagecollected. This is the article only covers what happens on the Sun JVM, other jvmsmay differ in procedure. A Simple Example

I ' ll start with a small class this doesn ' t cause any finalization and so we can clearly the differences. My Test1 Class (Listing 1) are simple loop that just creates anddereferences instances of Test1. It runs just as your would expectit to-creating lots of garbage instances, with the Garbagecollector kicking in Periodica Lly to the garbage.

public class Test1
{
  static long numberofcreatedinstances = 0;
  static long numberofdeletedinstances = 0;
  Public Test1 () {numberofcreatedinstances++;}

  static public void Main (String args[])
  {
    System.out.println ("Starting ...");
    for (int i = 0;; i++) {
      Test1 obj = new Test1 ();
      obj = null;
      if (i%10000000 = = 0)
      {
        System.out.println (
          numberofcreatedinstances-numberofdeletedinstances);
      }
    }
  }
}
Listing 1:the Test1 Class

Now I'll change the Test1 very slightly by making it finalizable. I ' ve called this class Test2 (listing 2). I ' ve added just one tiny method,highlighted in the code. Doesn ' t seem like much, I don ' t even call Thatmethod from my code. But as I ' m sure you know, it's the Specialfinalize () method, which called by the garbage when the collector Be reclaimed.

Class Test2
{
  static long numberofcreatedinstances = 0;
  static long numberofdeletedinstances = 0;
  Public Test2 () {numberofcreatedinstances++;}

  static public void Main (String args[])
  {
    System.out.println ("Starting ...");
    for (int i = 0;; i++) {
      Test2 obj = new Test2 ();
      obj = null;
      if (i%10000000 = = 0)
      {
        System.out.println (
          numberofcreatedinstances-numberofdeletedinstances);
      }
    }
  }

  protected void Finalize ()
  {
	  numberofdeletedinstances++
  }

}
Listing 2:the Test2 class-the only difference, the Test1 class is the addition of a finalize () method

It seems like there isn't much of a difference between Test1 and test2.but if I run the two programs, (THE-VERBOSE:GC op tion is particularly useful here), then I to very very different activities between. Test1 happily sails along, creating objects continuously,interrupted-occasionally by very fast young generations Gcs-jus T Exactlyas you would expect from looking at the code.

Test2, on the other hand, slows down to a crawl in comparison (with Maywant to limit the heap to 64m with-xmx64m, or even Lower). If you are runTest2 on a JVM earlier than a 1.6 JVM, then Test2 'll very likelyproduce an outofmemoryerror! (It might take a while.) On a 1.6+ jvm,it'll probably limp along indefinitely, going quite slowly, or itmight produce an outofmemoryerror, depend ing on the system you runit on.

You might is expecting this pattern if you are have previously readabout or encountered the cost of finalizers. Or Maybe it ' s a surprise. It was certainly a surprise to me when I-I-I-it-a Java Programthat has very code, and is little not definitely Ding on to morethan one object according to the code, produces an outofmemoryerror! Even those of your who were expecting this might still besurprised at the exact details of what are happening here. A Simple Lifecycle

Let ' s start with Test1. This is a straightforward class with instancesthat have a straightforward lifecycle. In the main () method, a Test1 objectis created in the Eden space of the young generation at New Test1 () (1). Then the "explicit dereference in the" very next line (obj = null;) eliminates any reference to that object (actually if Line wasn ' t there, the dereference would occur inthe Next loop iteration when obj. Set to point atthe next Test1 E, but I wanted to being explicit in the example).



Figure 1:new objects getting created in Eden

At some point, we have created enough Test1 instances this Eden getsfull-and that triggers a young generation garbage co Llection (usuallytermed "minor GC"). As nothing points to the "Objects in Eden" (or possibly Oneinstance is still referenced depending on when the GC OCCU RS), Eden is simply set to empty very efficiently by the garbagecollector (if one object is referenced Willbe copied to a survivor spaces I, figure 2) and presto, we are very, efficiently and empty In the loop continues with further object creation.



Figure 2: A minor GC empties out Eden


creation of A Finalizer

Test2, on the other hand, looks rather different. When a test2instance was created, the JVM detects it has a finalize () method which isdifferent from the one Defin Ed in the Object class. Yes, defining Anon-trivial Finalize () method in a class-or inheriting one for Thatmatter-is on it's own sufficient to Change how objects are created inthe JVM.

The JVM ignore a trivial finalize () method (e.g. one which justreturns without doing anything, like the one defined I n the objectclass). Otherwise, if an instance are being created, and that Instancehas a non-trivial Finalize () method defined or inherited, the N THEJVM'll do the following:the JVM would create the instance the JVM would also create an instance of the Java.lang.ref . Finalizerclass, pointing to "that" object instance just created (and pointing toa queue that it'll be put on by the GC) Th E Java.lang.ref.Finalizer class holds on to Thejava.lang.ref.Finalizer instance this is just created (so this it iskept a Live, otherwise nothing would keep it alive and it would begced at the next GC).

So this is what happens here with Test2. With every instance of test2created, we have a separate instance java.lang.ref.Finalizerpointing of Test2 to the instance. (Figure 3)



Figure 3:finalizable objects have a Finalizer created with them

Sound bad? So, it isn ' t particularly. I mean, okay we create twoobjects instead of one each time, but honestly the modern JVM isfantastically efficient at creat ing objects, so this is really isn ' ta big deal. The A- GC

OK that is the creation of a non-trivial Finalize () method, but what happens next? Just as before, the Test2 instancesare dereferenced, so can be garbage collected. So in some point Theyoung generation Eden gets full, and a minor GC happens. But Thistime Round, the GC has extra work to do. Firstly, instead of abunch of objects which aren ' t being referenced, we have lots of Objectswhich are, referenced from Fina Lizer objects, which in turn arereferenced class. So everything stays alive! THEGC'll copy everything into the survivor space. And if that's isn ' t big enough to hold all of the objects, it'll have to move some tothe old generation (which has a much More expensive GC cycle). Straight away we have significantly more work and are alsostoring the up significantly to more work for later.

But that's not even the "end of it." Because the GC recognizes thatnothing else points to the Test2 instances-apart, so it finalizers to says "a ha! I can process any finalizers which point to those test2instances ". So the GC adds each of those finalizerobjects to the reference queue at Java.lang.ref.Finalizer.ReferenceQueue. Now the GC is finally finished, has done quite a bit more workthan when we didn ' t have finalizers into Test1-and look a T the state's our JVM. Test2 instances are hangingaround, spread all over the place in survivor spaces and the oldgeneration too; Finalizer instances are hanging around too, as Theyare still referenced from the Finalizer class (for the figure 4). The GC is finished, but no seems to have been cleared



Figure 4:finalizable objects don ' t get cleared on the the the the the the the the the the The Finalizer Thread

Now, the minor GC are finished, the application threads start up again (they were suspended while the minor GC was Runni NG). Amongst the applicationthreads are Test2 's "main" thread, Andseveral threads the started by the Jvm-and one in particular CO Ncerns us:the "Finalizer" daemon thread. In which same java.lang.ref.Finalizerclass is a inner class called Finalizerthread which starts the "Finalizer" daemon EAD when the Java.lang.ref.Finalizer was loadedin to the JVM.

The "Finalizer" daemon thread is quite a simple thread. It sits Ina loop which is blocked waiting for something to become availableto being popped from the JAVA.LANG.REF.FINALIZER.R Eferencequeue queue. Conceptually, it looks like the loop in Listing 3 (the actual loop are a bit more complicated to handlevarious error and ACC ESS issues).

for (;;)
{
  Finalizer f = java.lang.ref.Finalizer.ReferenceQueue.remove ();
  F.get (). Finalize ();
}
Listing 3: A conceptual version of the Finalizer thread loop

So-we have a bit of a contention issue for the JVM heap resources. The main () loop has kicked back in and are producing lots moreTest2 instances, with their associated Finalizer, objects Leat the same time the ' Finalizer ' daemon thread is running throughthe the Finalizer objects ' the last GC pushed onto the Finalizerreference queue.

That would probably is fine-calling our test2.finalize () methodshould to quicker than a new creating Test2, so We ' dexpect to is able to catch up with and get ahead by the next GC. Onlythere is one little problem and that optimistic expectation. The "Finalizer" daemon thread is run in a lower priority by THEJVM than the default thread priority. Which means that's "main" thread gets lots more CPU time than the "Finalizer" Daemon Threadso, in Test2, it'll never CA Tch up.

In a normal application, this imbalance doesn ' t matter. finalizableobjects aren ' t usually created at such a high rate, and even where Theymight is created at a high rate in burst s as you can get in someapplications, your average application'll have some idle cputime which would let the "Finalizer" Daemon thread catch up.

But we Test2 class is a pathological finalizable class. It doescreate finalizable objects too fast for the ' Finalizer ' daemon thread tocatch up, and so that Finalizer reference q Ueue just keeps on buildingin size. The Second GC

Nevertheless, some Finalizer objects'll get out of the queue, and TheTest2 instances point to'll get they finalize ( ) methodscalled. At this point, the "Finalizer" daemon thread also doesone more job-it removes the reference to the Finalizer Classto t Hat Finalizer instance It just Processed-remember, which Iswhat was keeping the Finalizer instance. Now nothingpoints to the Finalizer instance, and it can is collected in the next gc-as can the Test2 instance since Noth ing else pointsto that.

So eventually, another GC'll happen. And this timeround, those Finalizer objects that have been processed'll getcleared out by the GC. That's the end of the lifecycle for Theones, the get-to-that stage. The others, still in the finalizerreference queue, would get cycled through the Survivor, spaces'll get process Ed and cleared, but most (in our TEST2 application) would eventually end of the old generation. Eventually, the old Generationwill also is full, and a major GC would occur. But the major gc,while capable of being a bit more thorough than the minor gcs,doesn ' t really can The outofmemoryerroroccurs. That queue just keeps growing, and eventually there isn ' tsufficient spaces to create new objects, and POW, we hit the oome.

(in 1.6, at least in some configurations, it looks like thegarbage collector has the smarts to is enough to try and able E Finalizer thread run a bit so this it can limp along, withthe heap almost full indefinitely. It ' s better than an oome crash,but isn't by much). Fixing It

This article is primarily about seeing how finalizable objects are. theactual example we used is pathological, so I could demonstrate finalizable objects Lifecyclein a dramatic way-t He vast majority of apps using finalizers would never to the a significant queue build up. Nevertheless, there are some apps that have hit "This finalizer \ Queue build up problem in the past, so it Isworth consideri Ng deal with it. One obvious way is to increasethe priority of the ' Finalizer ' daemon Thread-there is no APIs for this, so you have to run Through all of the threads to find it by name, then increase it ' spriority.

You are could also take explicit control over finalization through removing the Finalize () method andusing your own \ Explicit queue Using your own Reference objectsin a very similar way that the Finalizer class processes the objects and their finalize () Methods (for example Tony Printezis ' article). That way your control your finalization processing thread ' s priority and schedule.

Note that neither of those techniques reduce the overheads in have finalizable objects,they just avoid the queue Buildin G up because of the lower priority thread. Bear in Mindthat:the vast majority of apps using finalizers would never to a significant queue build up;but Heads of the having finalizable objects are significant. It ' s a good idea totry to keep the number of finalizable objects to a minimum. A few finalizable objects normally don ' t matter;too many can seriously the GC.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.