An example of a memory overflow solution for Android programming (OOM) is summarized _android

Source: Internet
Author: User
Tags garbage collection object object sleep

This example summarizes the memory overflow solution for Android programming (OOM). Share to everyone for your reference, specific as follows:

Oom problems often occur when you see too many pictures loaded or when pictures are too large in a recent project. Looking for information on the Internet also provides a lot of methods, but I feel a bit messy, hereby, today in different models of three Android mobile phone to do the test, because there are results, the pony today to do a detailed summary, For our friends to learn together, also for their later in solving the problem of oom to improve, in advance, the film is a bit long, involved in too many things, we patiently look, there must be harvest, there are a lot of things in the pony is also learning to use the reference network information, first of all simple to talk down:

In general, we all in the memory problem when the commonly used way online also have relevant information, roughly the following:

One: the memory reference to do some processing, commonly used soft references, enhanced references, weak references
Second: In memory loading pictures directly in memory to do processing, such as: Boundary compression
Three: Dynamically reclaim memory
Four: Optimize heap memory allocation for Dalvik virtual machines
Five: Custom heap memory size

But is it really that simple, with the above method can solve the oom? No, keep looking.

The pony follows the order of the above to sort out several ways, the numeric serial number corresponds to the above:

1: Soft references (softreference), virtual references (phantomrefrence), weak references (WeakReference), these three classes are applications to Java objects in heap, and this three class can do simple interactions with the GC. In addition to these three, there is one of the most commonly used strong references

1.1: Strong references, such as the following code:

Object O=new object ();   
Object o1=o; 

The first sentence in the above code is to create a new object object in the heap heap by using O, and the second sentence is a reference to an object in the heap heap that is created by O O1 to the new object (). Both references are strong references. The GC does not collect this object as long as there is a reference to the object in the heap. If you pass the following code:

O=null;   
O1=null

In heap, objects have strong objects, soft objects, weakly reachable objects, virtual objects and unreachable objects. The application is strong, soft, weak, and virtual. The object is the object of which it belongs, and is determined by his strongest reference. As follows:

String Abc=new string ("abc"); 1   
softreference<string> abcsoftref=new softreference<string> (ABC);//2   
weakreference< string> abcweakref = new weakreference<string> (ABC); 3   
abc=null//4   
abcsoftref.clear ();//5  

In the code above:

The first line creates an object with the content "ABC" in the heap pair and establishes a strong reference to the ABC to the object, which is strongly accessible. The second and third lines establish soft and weak references to objects in the heap, and the objects in heap are still strong. After the end of the line, the objects in the heap are no longer strong, and become soft and accessible. Similarly, the fifth line has become weak after its implementation.

1.2: Soft References

Soft references are primarily used for memory-sensitive caching. All soft references are purged before the JVM reports out of memory, which makes it possible for the GC to collect soft objects, possibly resolving memory crunch problems and avoiding memory overruns. When it will be collected depends on the algorithm of the GC and the size of the available memory at the time of the GC run. When GC decides to collect soft references is to perform the following procedure, take the abcsoftref above as an example:

1 First set the abcsoftref referent to null and no longer reference the new String ("ABC") object in heap.

2 The new String ("ABC") object in heap is set to be closed (finalizable).

3 when the Finalize () method of the new String ("ABC") object in Heap is run and the memory occupied by the object is released, Abcsoftref is added to its referencequeue.

Note: There can be none for referencequeue soft references and weak references, but virtual references must be available, see:
Reference (T Paramt, referencequeue<? Super T>paramreferencequeue)

Objects that are referred to by Soft Reference are not purged even if they do not have any Direct Reference. Until the JVM is out of memory and there is no Direct Reference, the softreference is used to design object-cache. As a result, softreference can not only cache objects, but also do not cause out-of-memory errors (outofmemoryerror). I think Soft Reference is also suitable for pooling skills.

A obj = new A ();  
refenrence sr = new SoftReference (obj);  
Reference Time  
if (sr!=null) {  
  obj = Sr.get ();  
} else{  
  obj = new A ();  
  sr = new SoftReference (obj);  
}  

1.3: Weak reference

When the GC encounters a weakly accessible object and releases the Abcweakref reference, the object is collected. But the GC may need to use this to find the weak object. The following code makes it clear how it works:

String Abc=new string ("abc");   
weakreference<string> abcweakref = new weakreference<string> (ABC);   
Abc=null;   
SYSTEM.OUT.PRINTLN ("Before GC:" +abcweakref.get ());   
System.GC ();   
SYSTEM.OUT.PRINTLN ("After GC:" +abcweakref.get ());  

Run Result:

Before GC:ABC
After Gc:null

GC collects weak and soft objects, but the GC does not decide whether to collect the object based on memory conditions. If you want to be able to get information about an object at any time, but do not want to affect the object's garbage collection, then you should use Weak Reference to remember this object, rather than the general Reference.

A obj = new A ();  
  WeakReference wr = new WeakReference (obj);  
  obj = null;  
  Wait for a while, the Obj object will be garbage collected ...  
if (Wr.get () ==null) {  
System.out.println ("obj has been cleared");  
}  else {  
System.out.println ("obj has not been purged, and its information is" +obj.tostring ()); 
} 
... 
} 

In this example, a get () can obtain the object that this Reference refers to, and if the return value is NULL, the object is cleared. Such techniques are often used in designing programs such as Optimizer or Debugger, because such programs need to obtain information about an object, but they do not affect garbage collection for that object.

1.4: Virtual Reference

It is not meant to be true that after a virtual reference is made, the result returned by the Get method is always null, and through the source code you will find that the virtual reference leads to the referent of the referenced object, but only the Get method returns the result null. Take a look at the process of interacting with the GC to say

1.4.1 does not set referent to NULL, it directly sets the new String ("ABC") object in heap to be closed (finalizable).

1.4.2, unlike soft references and weak references, first add the Phantomrefrence object to its referencequeue. Then the virtual object is released.

You will find that you can do something else before you collect the new String ("ABC") object in heap. You can understand his role through the following code.

Import java.lang.ref.PhantomReference;   
Import java.lang.ref.Reference;   
Import Java.lang.ref.ReferenceQueue;   
Import Java.lang.reflect.Field;   
  public class Test {public static Boolean isrun = true;   
    public static void Main (string[] args) throws Exception {String abc = new String ("abc");   
    System.out.println (Abc.getclass () + "@" + abc.hashcode ());
    Final Referencequeue referencequeue = new referencequeue<string> ();   
          New Thread () {public void run () {while (Isrun) {Object o = Referencequeue.poll (); if (o!= null) {try {Field rereferent = Reference.class.   
              Getdeclaredfield ("referent");   
              Rereferent.setaccessible (TRUE);   
              Object result = Rereferent.get (o); SYSTEM.OUT.PRINTLN ("GC'll collect:" + result.getclass () + "@" + result.hashcod   
           E ()); catch (Exception e) {e.printstacktrace ();   
    }}}}.start ();   
    phantomreference<string> abcweakref = new phantomreference<string> (ABC, referencequeue);   
    ABC = NULL;   
    Thread.CurrentThread (). Sleep (3000);   
    System.GC ();   
    Thread.CurrentThread (). Sleep (3000);   
  Isrun = false;
 }   
}

Result is

Class java.lang.string@96354
GC would collect:class java.lang.string@96354

Okay, here's the reference, look at the 2.

2: In memory compressed pony did the next test, for a small number of not too big picture this way feasible, but too much and big picture pony with a stupid way is, first in memory compression, and then use soft reference to avoid oom, the two ways of code as follows, you can refer to:

The way one code is as follows:

@SuppressWarnings ("unused") Private Bitmap Copressimage (String imgpath) {File picture = new file (Imgpath);
  Options bitmapfactoryoptions = new Bitmapfactory.options ();
  The following setting is to change the picture boundary to an adjustable bitmapfactoryoptions.injustdecodebounds = true;
  Bitmapfactoryoptions.insamplesize = 2;
  int outwidth = Bitmapfactoryoptions.outwidth;
  int outheight = Bitmapfactoryoptions.outheight;
  Bmap = Bitmapfactory.decodefile (Picture.getabsolutepath (), bitmapfactoryoptions);
  float Imagew = 150;
  float Imageh = 150;
  int yratio = (int) math.ceil (Bitmapfactoryoptions.outheight/imageh);
  int xratio = (int) Math. ceil (Bitmapfactoryoptions.outwidth/imagew);
    if (Yratio > 1 | | xratio > 1) {if (Yratio > Xratio) {bitmapfactoryoptions.insamplesize = Yratio;
    else {bitmapfactoryoptions.insamplesize = Xratio;
  } bitmapfactoryoptions.injustdecodebounds = false; Bmap = Bitmapfactory.decodefile (Picture.getabsolutepath (), bitmapfactOryoptions);
    if (bmap!= null) {//ivwcouponimage.setimagebitmap (BMAP);
  return bmap;
return null;

 }

Mode two code is as follows:

Package com.lvguo.scanstreet.activity;
Import Java.io.File;
Import java.lang.ref.SoftReference;
Import java.util.ArrayList;
Import Java.util.HashMap;
Import java.util.List;
Import android.app.Activity;
Import Android.app.AlertDialog;
Import Android.content.Context;
Import Android.content.DialogInterface;
Import android.content.Intent;
Import Android.content.res.TypedArray;
Import Android.graphics.Bitmap;
Import Android.graphics.BitmapFactory;
Import android.graphics.BitmapFactory.Options;
Import Android.os.Bundle;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.view.WindowManager;
Import Android.widget.AdapterView;
Import Android.widget.AdapterView.OnItemLongClickListener;
Import Android.widget.BaseAdapter;
Import Android.widget.Gallery;
Import Android.widget.ImageView;
Import Android.widget.Toast;
Import COM.LVGUO.SCANSTREET.R;
Import Com.lvguo.scanstreet.data.ApplicationData; /** * @Title: Photoscanactivity.java * @Description: Photo Preview Control class * @author Xiaoma/PUblic class Photoscanactivity extends activity {private Gallery Gallery;
  Private list<string> ImageList;
  Private list<string> it; 
  Private Imageadapter adapter;
  Private String path;
  Private String Shoptype;
  Private hashmap<string, softreference<bitmap>> imagecache = null;
  Private Bitmap Bitmap = null;
  Private softreference<bitmap> SRF = null;
    @Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
    GetWindow (). SetFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    Setcontentview (R.layout.photoscan);
    Intent Intent = This.getintent (); if (intent!= null) {if (Intent.getbundleextra ("bundle")!= null) {Bundle bundle = Intent.getbundleextra ("Bund
        Le ");
        Path = bundle.getstring ("path");
      Shoptype = bundle.getstring ("Shoptype");
  } init (); private void Init () {Imagecache = new HashMap<string, softreference<bitmap>> ();
     Gallery = (gallery) Findviewbyid (r.id.gallery);
     ImageList = GETSD ();
      if (imagelist.size () = = 0) {Toast.maketext (Getapplicationcontext (), "No photo, please return to the photo before using preview", Toast.length_short). Show ();
     return;
     } adapter = new Imageadapter (this, ImageList);
     Gallery.setadapter (adapter);
  Gallery.setonitemlongclicklistener (Longlistener); /** * Gallery Long by Event operation implementation/private Onitemlongclicklistener Longlistener = new Onitemlongclicklistener () {@O
      Verride public Boolean Onitemlongclick (adapterview<?> parent, view view, final int position, long ID) {
      Here add long by event Delete Photo Implementation Alertdialog.builder Dialog = new Alertdialog.builder (photoscanactivity.this);
      Dialog.seticon (R.drawable.warn);
      Dialog.settitle ("delete hint"); Dialog.setmessage ("Are you sure you want to delete this picture?")
      "); Dialog.setpositivebutton (OK), new Dialoginterface.onclicklistener () {@Override public void OnClick(dialoginterface dialog, int which)
          {File File = new file (It.get (position));
          Boolean issuccess;
            if (file.exists ()) {issuccess = File.delete ();
              if (issuccess) {imagelist.remove (position);
              Adapter.notifydatasetchanged ();
              Gallery.setadapter (adapter); if (imagelist.size () = = 0) {Toast.maketext (Getapplicationcontext (), Getresources (). getString (R.string.phosi
              Zezero), Toast.length_short). Show (); } toast.maketext (Getapplicationcontext (), Getresources (). getString (r.string.phodelsuccess), Toast.length_sho
            RT). Show ();
      }
          }
        }
      }); Dialog.setnegativebutton ("Cancel", new Dialoginterface.onclicklistener () {@Override public void OnClick (dialog
        Interface dialog, int which) {Dialog.dismiss ();
      }
      });
      Dialog.create (). Show ();
    return false;
  }
  }; /** * get all on SD cardPicture file * @return/private list<string> GETSD () {/* Set the current path/file Filek;
    it = new arraylist<string> ();
    if ("Newadd". Equals (Shoptype)) {//If you come in from the view of my new list item or merchant list entry Filek = new File (applicationdata.temp);
    }else{//At this time for pure add Filek = new File (path);
    } file[] files = filek.listfiles ();
          if (Files!= null && files.length>0) {for (File f:files) {if (Getimagefile (F.getname ())) {
          It.add (F.getpath ());
          Options bitmapfactoryoptions = new Bitmapfactory.options ();
          The following setting is to change the picture boundary to an adjustable bitmapfactoryoptions.injustdecodebounds = true;
          Bitmapfactoryoptions.insamplesize = 5;
          int outwidth = Bitmapfactoryoptions.outwidth;
          int outheight = Bitmapfactoryoptions.outheight;
          float Imagew = 150;
          float Imageh = 150;
          int yratio = (int) math.ceil (Bitmapfactoryoptions.outheight/imageh); int XRAtio = (int) Math. ceil (Bitmapfactoryoptions.outwidth/imagew); if (Yratio > 1 | | xratio > 1) {if (Yratio > Xratio) {bitmapfactoryoptions.insamplesiz
            e = Yratio;
            else {bitmapfactoryoptions.insamplesize = Xratio;
          } bitmapfactoryoptions.injustdecodebounds = false;
          Bitmap = Bitmapfactory.decodefile (F.getpath (), bitmapfactoryoptions); 
          Bitmap = Bitmapfactory.decodefile (F.getpath ());
          SRF = new softreference<bitmap> (BITMAP);
        Imagecache.put (F.getname (), SRF);
  }} return it; /** * Obtain the concrete implementation of the image file method * @param fName * @return/private Boolean getimagefile (String fName) {Boolea
    n Re;
    /* Get extension/String end = fName. Substring (Fname.lastindexof (".") + 1, fname.length ()). toLowerCase (); /* Determines mimetype/if (end.equals ("JPG") by the type of extension.Equals ("gif") | | End.equals ("png") | | End.equals ("JPEG") | |
    End.equals ("BMP")) {re = true;
    else {re = false;
  return to re;
    The public class Imageadapter extends baseadapter{/* declares variable/int mgalleryitembackground;
    Private context Mcontext;
    Private list<string> lis;
      /* Imageadapter constructor/Public Imageadapter (context C, list<string> li) {mcontext = C;
      lis = Li;
      TypedArray a = obtainstyledattributes (r.styleable.gallery);
      Mgalleryitembackground = A.getresourceid (r.styleable.gallery_android_galleryitembackground, 0);
    A.recycle ();
    }/* Several methods to rewrite GetCount, return the number of pictures/public int getcount () {returns lis.size ();
    }/* must override the method GetItem, return position/public Object getitem (int position) {returns lis.get (position);
    }/* must override the method Getitemid, pass and position/public long getitemid (int position) {return position;
    }/* Several methods to rewrite GetView, and a few view objectsPublic View GetView (int position, View Convertview, ViewGroup parent) {System.out.println ("lis:" +lis);
      File File = new file (It.get (position));
      Softreference<bitmap> SRF = Imagecache.get (File.getname ());
      Bitmap bit = Srf.get ();
      ImageView i = new ImageView (mcontext);
      I.setimagebitmap (bit);
      I.setscaletype (ImageView.ScaleType.FIT_XY); I.setlayoutparams (New Gallery.layoutparams, WindowManager.LayoutParams.WRAP_CONTENT, Windowmanager.layoutparams.
      Wrap_content));
    return i;

 }
  }
}

The first two ways to direct the use of boundary compression, the second in the use of boundary compression in the case of indirect use of soft references to avoid oom, but we all know that these functions after completion of the decode, ultimately through the Java layer of the CreateBitmap to complete, need to consume more memory, If the picture is many and big, this kind of way still will quote oom unusual, do not worry, have some solution, continue to look, the following way also has great magical use of:

1.

InputStream is = This.getresources (). Openrawresource (R.DRAWABLE.PIC1);
Bitmapfactory.options options=new bitmapfactory.options ();
Options.injustdecodebounds = false;
Options.insamplesize = ten;  Width,hight is set to the original very
Bitmap BTP =bitmapfactory.decodestream (is,null,options);

2.

if (!bmp.isrecycle ()) {
     bmp.recycle ()  ///Reclaim the memory of the picture
     System.GC ()//remind the system to recycle in time
}

The above code and the following code can be used separately, can also effectively alleviate the memory problem oh ... Roar ...

/** this place don't mix up, in order to facilitate the pony put two together, use the time to remember to separate use
* in the most province of memory to read the picture of local resources * * Public 
static Bitmap Readbitmap context, int resid) { 
    bitmapfactory.options opt = new bitmapfactory.options (); 
    Opt.inpreferredconfig = Bitmap.Config.RGB_565;  
    Opt.inpurgeable = true; 
    Opt.ininputshareable = true; 
     Get resource picture 
    InputStream is = Context.getresources (). Openrawresource (RESID); 
      Return Bitmapfactory.decodestream (is,null,opt); 
}

3: You can choose to use the following code dynamically and call the GC explicitly to reclaim the memory at the right place:

if (bitmapobject.isrecycled () ==false)//If no recycle 
     bitmapobject.recycle ();  

4: This is fun, optimize the Dalvik virtual machine heap memory allocation, listen very powerful, look at the specific is how

For the Android platform, the Dalvik JAVAVM used by its hosting layer can be optimized for the present performance, such as we may consider manual interference GC processing in the development of some large games or resource-consuming applications, using The Settargetheaputilization method provided by the Dalvik.system.VMRuntime class can enhance the processing efficiency of the program heap memory. Of course, we can refer to the specific principles of open source Engineering, here we only said the use of: The code is as follows:

Copy Code code as follows:
Private final static floattarget_heap_utilization = 0.75f;

When the program is OnCreate, you can call
Copy Code code as follows:
Vmruntime.getruntime (). Settargetheaputilization (target_heap_utilization);

Can

5: Customize our application needs how much memory, this good violence wow, forced to set the minimum memory size, the code is as follows:

Private final static int cwj_heap_size = 6* 1024* 1024;
 Set minimum HEAP memory to 6MB size
vmruntime.getruntime (). Setminimumheapsize (Cwj_heap_size);

Well, the article is finished, the piece is a bit long, because there are too many things involved, other articles pony will paste the source code, this article pony is directly in the project with three An Zuojin machine test, has the effect, the project original code is not in this paste, or leaks all, roar, but here it will be because the phone is different and different, We have to choose the right way according to their needs to avoid oom, everyone refueling ah, every day have more or less harvest, which is also progress, refueling!

I hope this article will help you with the Android program.

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.