[Java] Monitoring the principle and implementation of Java object Recycling

Source: Internet
Author: User

Principle and implementation of monitoring Java object Recycling

A Monitoring the purpose of Java object Recycling

The purpose of monitoring whether Java objects are recycled is to implement a memory leak alarm.

Memory leak refers to the object life cycle of the program (click to view details) has entered the invisible phase, but because of coding errors or system reasons, there is still a GC roots hold or indirectly hold the object's reference, resulting in the object's life cycle can not continue to flow downward, it will not be released.

In simple terms, an instantiated object is held for a long time and cannot be released or released in accordance with the normal life cycle of the object.

(Click here to see "[Android] Memory leak Troubleshooting Manual")

Implement a memory leak alarm. can detect and solve coding errors on the program, reduce the memory usage of the application and reduce the chance of applying oom.

In my Android development, the object of monitoring is activity.

Two Monitoring the principle of Java object Recycling

In 1.

Object x loses all strong references after it has been lost (plain Java objects are all strong references in the lost. In Android, the OnDestroy () method is run as activity. The feature log for the object x is added to Listgclog and then listgclog into the yellow wait time area, assuming that object x is terminated normally during that wait time, and the feature log of the object is removed from Listgclog. Assuming that the wait time is still not terminated, the time is over. The program checks if Listgclog is empty. And make a memory leak alarm when it is not empty.

Figure 1. Monitoring of objects

Three Time to monitor Java object Recycling

Suppose a Java object has been retrieved? There are 3 ways to do this:

1. The Java object runs the Finalize () method

The implementation of this method is based on each object before being reclaimed by the garbage collector. Will call the Finalize () method of the object.

Within the Finalize () method, run the delete X feature log from LISTGC in Figure 1. That is, it does not cause a memory leak alarm.

But this is not a good way to achieve it. When the object is assigned. The JVM needs to register the object on the garbage collector. To be able to run the overloaded method at recycle time, the method runs with CPU time and the recycle operation is run after the method is run, that is, at least two GC is required to be run by the garbage collector on the object.

See 2. The Reclaim time for the rewrite Finalize () method is many times longer than that of a normal object. When the test quantity is 10000. The former consumes 433ms is nearly 5 times times the latter 95ms, when the number of times, the time gap is increasing, when the test number reached 50,000, the former consumes 7553ms is 35 times times the latter 217ms.

Figure 2. Time consumption comparison chart for object recycling

2. Use WeakReferences (weak reference) when Weakreferences.get () returns NULL. That is, the object that represents the weak reference is already or is in the garbage collector recycle phase.

Weakly referenced objects have a shorter life cycle than strong references and soft references.

In the process of scanning the area of memory that the garbage collector thread governs. Once an object with only a weak reference is found, no matter whether the current memory space is sufficient or not. Will reclaim its memory.

The value returned by the Get () method is null when the weakly referenced object has been or is in the garbage collector recycle phase. The operation to delete the X feature log from LISTGC in Figure 1 is now running, which will not cause a memory leak alarm.

3. Use Phantomreferences (virtual Reference) and Referencequeue (reference queue) when Phantomreferences is added to the associated referencequeue. The object is considered to be or is in the garbage collector recycle phase.

Virtual references are primarily used to track activities that objects are reclaimed by the garbage collector. Virtual references must be used in conjunction with the reference queue (Referencequeue). When the garbage collector prepares to reclaim an object, it is assumed that it has a virtual reference, and that the virtual reference is added to the reference queue associated with it before the object's memory is reclaimed.

The program is able to understand whether the referenced object will be garbage collected by inferring whether a virtual reference has been added to the reference queue.

Assuming the program discovers that a virtual reference has been added to the reference queue, it is able to take the necessary action before the memory of the referenced object is recycled. The operation to delete the X feature log from LISTGC is run in Figure 1. That is, it does not cause a memory leak alarm.

In the implementation of the 2nd and 3 methods, the weak-referenced get () returns null and whether the virtual reference is added to the reference queue. The system does not provide a callback interface, so in the code implementation, you need to open a sub-thread to check.

The implementation of the above three methods enables the VM to run the recycle operation on objects that have lost a strong reference as soon as possible by running the System.GC () operation multiple times. But "urging" means to be as early as possible, not to run immediately.

In fact, the phanomreferences in Method 3 is also able to replace the implementation with WeakReferences. But there are some differences between the two. See 3.

A weak reference object is cleared before the Finalize () method is run, and the virtual reference object is cleared after the Finalize () method finishes running.

Since the Finalize () method is run, the object is again assigned to a strong reference, so from a finer point of view, it is most accurate to infer whether the object is recycled by using a virtual reference + reference queue method.

Figure 3. State transition process for objects

Four Code implementation to monitor Java object Recycling

The code in this article is implemented on Android, can add QQ group Code2share (363267446), from the group shared files to download. Do not want to add a group of "diligent () Bee" can also be described in the following description of their own code to achieve it.
This article belongs to Sodino original. Posted in Blog: Http://blog.csdn.net/sodino. Reprint please indicate the source.
The relevant code can be downloaded from the group file in QQ Group Code2share (363267446).

4 is the demo sample code operation interface. Clicking on the "New" button will generate a specified number of Java objects. Clicking "Release" will start the object collection operation, after all the objects have been recycled. The time spent will be fed back to the interface.

Figure 4. Demo Sample Code operator interface

1. The Java object runs the Finalize () method

In the demo sample code, the code for creating objects in the Finalizeactivity, Weakreferencesactivity, phantomreferencesactivity three classes is almost the same way. Here is the NewObject () method under the finalizeactivity.

The created objects are added to the listbusiness in order to get the most accurate creation time possible. This adds the feature log operation independently after the creation of the code, each object will have the feature log added to the Listgclog, waiting for the recovery of the test.

   private void NewObject () {        txtresult.settext ("");        Finalizeobjectobj = null;        Long startnewtime= System.currenttimemillis ();        for (int i = 0;i < Number;i + +) {            obj= new finalizeobject (i);            Listbusiness.add (obj);        }        Final long consume =system.currenttimemillis ()-startnewtime;        Runonuithread (New Runnable () {                       @Override public            void Run () {                txtresult.settext ("new" + number + "objs,\ Nconsume: "+ consume +" MS ");                Btnnew.setenabled (false);                Btnrelease.setenabled (True);            }        });        for (int i = 0;i < Number;i + +) {            obj= listbusiness.get (i);            Listgclog.add (OBJ.IDSTR);        }        LOG.D ("Android_lab", "newObject" + number + "consume=" + consume);    }

Corresponding to the above NewObject () method, the trigger object is disposed of by the releaseobject () implementation of the following example:

    Private Voidreleaseobject () {        btnrelease.setenabled (false);        Startgctime = System.currenttimemillis ();        Listbusiness.clear ();        Clear the operation and tell the VM that there is a big lump of objects to eat        . System.GC ();    }

The most important thing is to define a class that overrides the Finalize () method. A member variable idstr of the class Finalizeobject represents a characteristic log that is unique to the class object and, in the Finalize () method, runs the Listgclog delete operation by inferring whether Listgclog includes the idstr.

When the size of Listgclog () is 0 o'clock. Indicates that all objects have been reclaimed, and that it is time to calculate the recycle of all objects and notify the UI refresh interface.

The code is as follows:

  classfinalizeobject {int id =-1;        Feature log stringidstr = null;            Publicfinalizeobject (int id) {this.id = ID;        THIS.IDSTR = integer.tostring (ID); } @Override public void Finalize () {Boolean contains = Listgclog.contains (Finalizeobject.            THIS.IDSTR);            if (contains) {//delete feature log: Isstr listgclog.remove (IDSTR); } if (listgclog.size () = = 0) {//All recycles have completed final long consume = (system.currenttim                Emillis ()-startgctime);                LOG.D ("Android_lab", "finalizesize=0, consumetime=" + Consume + "name=" +thread.currentthread (). GetName ());                        Runonuithread (New Runnable () {@Override public void run () {                        Stringnewobjstr = Txtresult.gettext (). toString (); Txtresult.settext (newobjstr+ "\N\NGC" + number + "Objs,\nconsume: "+ consume +" MS ");                        Btnnew.setenabled (TRUE);                    Btnrelease.setenabled (FALSE);            }                }); }        }    }

2. Using weakreferences (weak reference)

In the NewObject () method, Listgclog directly records the weakreferences corresponding to the object.

  classfinalizeobject {int id =-1;        Feature log stringidstr = null;            Publicfinalizeobject (int id) {this.id = ID;        THIS.IDSTR = integer.tostring (ID); } @Override public void Finalize () {Boolean contains = Listgclog.contains (Finalizeobject.            THIS.IDSTR);            if (contains) {//delete feature log: Isstr listgclog.remove (IDSTR); } if (listgclog.size () = = 0) {//All recycles have completed final long consume = (system.currenttim                Emillis ()-startgctime);                LOG.D ("Android_lab", "finalizesize=0, consumetime=" + Consume + "name=" +thread.currentthread (). GetName ());                        Runonuithread (New Runnable () {@Override public void run () {                        Stringnewobjstr = Txtresult.gettext (). toString (); Txtresult.settext (newobjstr+ "\N\NGC" + number + "Objs,\nconsume: "+ consume +" MS ");                        Btnnew.setenabled (TRUE);                    Btnrelease.setenabled (FALSE);            }                }); }        }    }

It is necessary to turn on the child thread to infer whether the weak reference get () returns NULL.

When the return value is NULL, the corresponding feature log is removed from the listgclog. When Listgclog.size () is 0 o'clock. It means that the VM has eaten up a big lump of objects.

  classfinalizeobject {int id =-1;        Feature log stringidstr = null;            Publicfinalizeobject (int id) {this.id = ID;        THIS.IDSTR = integer.tostring (ID); } @Override public void Finalize () {Boolean contains = Listgclog.contains (Finalizeobject.            THIS.IDSTR);            if (contains) {//delete feature log: Isstr listgclog.remove (IDSTR); } if (listgclog.size () = = 0) {//All recycles have completed final long consume = (system.currenttim                Emillis ()-startgctime);                LOG.D ("Android_lab", "finalizesize=0, consumetime=" + Consume + "name=" +thread.currentthread (). GetName ());                        Runonuithread (New Runnable () {@Override public void run () {                        Stringnewobjstr = Txtresult.gettext (). toString (); Txtresult.settext (newobjstr+ "\N\NGC" + number + "Objs,\nconsume: "+ consume +" MS ");                        Btnnew.setenabled (TRUE);                    Btnrelease.setenabled (FALSE);            }                }); }        }    }

3. Using phantomreferences (virtual Reference) and Referencequeue (reference queue)

The NewObject () method needs to be concerned with the creation of virtual reference objects. For example, stare in the following code:

   private void NewObject () {        txtresult.settext ("");        Pfobjectobj = null;        Long startnewtime= System.currenttimemillis ();        for (int i = 0;i < Number;i + +) {            obj= new pfobject (i);            Listbusiness.add (obj);        }        Long consume =system.currenttimemillis ()-startnewtime;        Showresult (true, consume);        for (int i = 0;i < Number;i + +) {            obj= listbusiness.get (i);            Passing an object into a constructed virtual reference. and associated with the reference queue            phantomreference<pfobject>phantomref  = newphantomreference<pfobject> (obj, Refqueue);            Listgclog.add (PHANTOMREF);        }        LOG.D ("Android_lab", "newObject" + number);    }

As with weakreferences, whether or not a virtual reference is added to the reference queue also requires that the thread continue to query the state. When Referencequeue.poll () returns is not NULL. Indicates that a virtual reference has been added to the reference queue. The ability to run Listglog.remove () clears the feature log of the object. The last Call to Showresult () displays the time.

private void Releaseobject () {    btnrelease.setenabled (false);    Newthread () {        publicvoid run () {            startgctime= system.currenttimemillis ();            Listbusiness.clear ();            Clear the operation and tell the VM that there is a big lump of objects to eat            . System.GC ();            intcount = 0;            while (count!= number) {                reference<?extends pfobject> ref = (REFERENCE<? extends pfobject>) Refqueue.poll ();                if (ref! = null) {                    Booleanbool = Listgclog.remove (ref);                    Clear the virtual reference.                    ref.clear ();                    count++;                }            }            Longconsume = System.currenttimemillis ()-startgctime;            LOG.D ("Android_lab", "Releaseobject () consume=" + consume);            Showresult (False,consume);        }    }. Start ();}


[Java] Monitoring the principles and implementation of Java object Recycling

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.