out of memory exception + analyzing hprof file dum

2019-02-12 14:45发布

this is in connection with this question

java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)

i created the dump file in question.. and it gives following information

One instance of "byte[]" loaded by "<system class loader>" occupies 1,10,59,216
(51.02%) bytes. The memory is accumulated in one instance of "byte[]" 
 loaded by "<system class loader>".

Keywords byte[]

so now what can be done?? how do i clear the problem??

my list_objects[context]-inbound file

CLASS NAME                                                                 SHALLOW HEAP   RETAINED HEAP  
byte[11059200] @ 0xb4979590                                               |  1,10,59,216 |   1,10,59,216
mBuffer android.graphics.Bitmap @ 0xb3dc68d8                              |48            | 48
mBitmap android.graphics.drawable.BitmapDrawable @ 0xb3dbba60             | 72           | 144
mBackground android.widget.RelativeLayout @ 0xb3db3fc0                    |512           | 10,144
mBitmap android.graphics.drawable.BitmapDrawable$BitmapState @ 0xb3dc0068 |40          | 40
mBitmapState android.graphics.drawable.BitmapDrawable @ 0xb3dbba60        |72          |  144
referent java.lang.ref.WeakReference @ 0xb3dc2d68                         |24          |  24

pls help i am desperate. how can i solve the memory problem??

my home_screen.java

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.home_page);
    main();
 private void main() {
    // TODO Auto-generated method stub


    final Button home;
    final Button aboutus;
    final Button contacts;
    final Button clients;
    final Button services;

    try
    {

    home = (Button)findViewById(R.id.btnHome);
    aboutus = (Button)findViewById(R.id.btnAboutus);
    clients = (Button)findViewById(R.id.btnClients);
    contacts = (Button)findViewById(R.id.btnContacts);
    services = (Button)findViewById(R.id.btnServices);

    home.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.home1);
            Drawable d = new BitmapDrawable(getResources(),b);              
            home.setBackgroundDrawable(d);
            System.gc();
            Intent myIntent = new Intent(Home_Screen.this, Button_Anime.class);
            startActivity(myIntent);
        }
    });
    aboutus.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.about1 );
            Drawable d = new BitmapDrawable(getResources(),b); 
            aboutus.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, AboutUs.class);
            startActivity(myIntent);
        }
    });
    clients.setOnClickListener(new  OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.clients1 );
            Drawable d = new BitmapDrawable(getResources(),b); 
            clients.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Clients.class);
            startActivity(myIntent);
        }
    });
    contacts.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.contact1);
            Drawable d = new BitmapDrawable(getResources(),b);
            contacts.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Contacts.class);
            startActivity(myIntent);
        }
    });
    services.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

            Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.services1 );
            Drawable d = new BitmapDrawable(getResources(),b);
            services.setBackgroundDrawable(d);
            Intent myIntent = new Intent(Home_Screen.this, Services.class);
            startActivity(myIntent);
        }
    });

    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

4条回答
闹够了就滚
2楼-- · 2019-02-12 15:16

Normally when i get this kind of exception on low Ram devices it's because i have some kind of image to expensive (many kb) for this resolution. I had a weird problem because i just used xhdpi and hdpi drawables directories, on mdpi or even ldpi devices the hdpi conversion to the right resolution raise this exception because cannot resize the image.

It's happens on any device? Could you check you have a specific graphics for this low devices?

Any way with HPOF file you can see what kind of object or at least, wich activity/view has the problem. You need to analyze all this data (there is no a master plan to find the resource it's collapsing your app) to see which has the problem.

Hope this helps, any question, please feel free to ask.

查看更多
啃猪蹄的小仙女
3楼-- · 2019-02-12 15:21

try the below code:

Resources res = getContext().getResources();
int id = R.drawable.image; 
Bitmap b = BitmapFactory.decodeResource(res, id);    
_img .setimagebitmap(b);
查看更多
ゆ 、 Hurt°
4楼-- · 2019-02-12 15:22

The idea is to down sample your image so that it looks good on the smaller screen and that you dont have to load the entire bitmap in memory.

1) First get the size of your ImageView/ screen that you will be displaying on.

2) Read the size of you Bitmap by passing in BitmapFactory.Options.inJustDecodeBounds. This will give you the size of the Bitmap rather than loading the entire bitmap.

3) Get a insample size. Calculate the ratio of height and width of the screen to the image height and width. Use the smallest one so that the biggest dimension looks good.

4) Final use the function below to get the down sampled image that wont eat up your memory.

2)(code)

BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, bitmapOptions);
int imageWidth = bitmapOptions.outWidth;
int imageHeight = bitmapOptions.outHeight;
inputStream.close();

4)(code)

private Bitmap downscaleBitmapUsingDensities(final int sampleSize,final int imageResId)
  {
  final Options bitmapOptions=new Options();
  bitmapOptions.inDensity=sampleSize;
  bitmapOptions.inTargetDensity=1;
  final Bitmap scaledBitmap=BitmapFactory.decodeResource(getResources(),imageResId,bitmapOptions);
  scaledBitmap.setDensity(Bitmap.DENSITY_NONE);
  return scaledBitmap;
  }
查看更多
何必那么认真
5楼-- · 2019-02-12 15:22

Adding largeHeap="true" in your manifest may help. This will allow your application to use more memory.

See: http://developer.android.com/guide/topics/manifest/application-element.html

查看更多
登录 后发表回答