首页 > 知识内容详情
oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)

oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)

所属分类:知识

发布时间:2025-11-11 16:37:13

更新日期:2025-11-11 16:37:13

标签:

官方网址:

SEO查询: 爱站网 站长网 5118

进入网站
标签ad报错:该广告ID(3)不存在。
网站及网址申请收录 本站只收录合法内容
内容介绍

本文目录

如何分析android的oom,与java静态代码分析工具

在Android平台上面,应用程序OOM异常永远都是值得关注的问题。通常这一块也是程序这中的重点之一。这下我就如何解决OOM作一点简单的介绍。 首先,OOM就是内存溢出,即Out Of Memory。也就是说内存占有量超过了VM所分配的最大。 怎么解决OOM,通常OOM都发生在需要用到大量内存的情况下(创建或解析Bitmap,分配特大的数组等),在这样的一种情况下,就可能出现OOM,据我现在了解到,多数OOM都是因为Bitmap太大。所以,这里我就专门针对如何解决Bitmap的OOM。其实最核发的就是只加载可见范围内的Bitmap,试想这样一种情况,在GridView或ListView中,数据量有5000,每一屏只显示20个元素,那么不可见的,我们是不需要保存Bitmap在内在中的。所以我们就是只把那么可见的Bitmap保留在内存中,那些不可见的,就释放掉。当元素滑出来时,再去加载Bitmap。 这里我有两种方式,都可以避免OOM。一,主动释放Bitmap的内存这种方式我简单说一下,不太推荐,这也是我最开始使用的一种方法,但最后证明它不是最好的。(不推荐) 它的本质思路是: 1、只加载可见区域的Bitmap 2、滑动时不加载 3、停止滑动(Idle)后,开始重新加载可见区域的图片 4、释放滑出可见区域的Bitmap的内在。 它比较复杂: 1、我们需要监听GridView/ListView的滑动事件,这个很简单做到,AbsListViewsetOnScrollListener(OnScrollListener l) 2、主动调用Bitmaprecycle()方法,它会导致一个问题,必须判断这个Bitmap是否被一个View(ImageView等)所引用,如果被引用,我们不能简单地调用recycle()方法,这样会导致异常,说是View使用了一个已经被回收的Bitmap。 3,我们必须设计自己的线程来控制开始/暂停等,因为GridView/ListView的滑动状态可能不断地变化,也就是说滑动-》停止-》滑动,这种状态可能不断变化,这样就会导致我们的线程中的run()方法里面的逻辑比较复杂,一旦复杂,问题就可能就得更多。 基于以上几点,这种方式不是最好的,所以不推荐。二,设计Cache 这种方式,我觉得是比较好的一种,它首先利用了cache,我认为cache是一个很重要的东西,把Bitmap的内存单独放在一个地方来管理,这个地方就是cache,它的容量是一定的,我们可能会不断的向这个cache中添加元素,也可能不断的移除元素。为了更好的说明这种方式,先要介绍一下LruCache。 LruCache 1、这其实就是一个LinkedHashMap,任意时刻,当一个值被访问时,它就会被移动到队列的开始位置,所以这也是为什么要用LinkedHashMap的原因,因为要频繁的做移动操作,为了提高性能,所以要用LinkedHashMap。当cache满了时,此时再向cache里面添加一个值,那么,在队列最后的值就会从队列里面移除,这个值就有可能被GC回收掉。

oom的解决方法有哪些,请说明

1. 正确释放drawable的方式:Bitmap bm = BitmapFactory.decodeResource(this.getResources(), R.drawable.splash);BitmapDrawable bd = new BitmapDrawable(this.getResources(), bm);mBtn.setBackgroundDrawable(bd);来代替mBtn.setBackgroundResource(R.drawable.splash)。销毁的时候使用:BitmapDrawable bd = (BitmapDrawable)mBtn.getBackground();mBtn.setBackgroundResource(0);//别忘了把背景设为null,避免onDraw刷新背景时候出现used a recycled bitmap错误bd.setCallback(null);bd.getBitmap().recycle();2. 使用字节流,突破Android heap size的限制从中不难发现,bitmap的存放位置根据Android版本的不同真的有所不同。好了,下面就是找出怎么把图片存放到native heap里就行了,BitmapFactory里就那么几个decode方法,很容易找到BitmapFactory .decodeStream就可以解决。下面贴一下代码:BitmapFactory.Options options = new BitmapFactory.Options();options.inPreferredConfig = Config.ARGB_8888;options.inPurgeable = true;// 允许可清除options.inInputShareable = true;// 以上options的两个属性必须联合使用才会有效果String sname = String.format( “xxx.png”, sTowerStyle, j, sDirction, i);InputStream is = am.open(sname);arrBmp = BitmapFactory .decodeStream(is, null, options);ok搞定收工。尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的秘密在于其直接调用JNI》》nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应, 使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源, 否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。

java oom异常怎么解决方案

在 Java中,JavaVM拥有自动管理内存的功能,Java的GC能够进行垃圾回收,但是Android中如果ImageView使用过多的Bitmap的话,经常会报OOM(内存溢出)。造成内存溢出及解决方案:1.使用BitmapFactory.decodeStream替代createBitmap方法原因是该方法直读取图片字节,调用JNI》》nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap。2.使用压缩读取技术BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(imageSdUri, options);final int height = options.outHeight;final int width = options.outWidth;options.inSampleSize = 1;int w = 320;int h = 480;h = w*height/width;//计算出宽高等比率int a = options.outWidth/ w;int b = options.outHeight / h;options.inSampleSize = Math.max(a, b);options.inJustDecodeBounds = false;Bitmap bitmap = BitmapFactory.decodeFile(imageSdUri, options);3.及时释放BitampBitmap对象在不使用时,我们应该先调用recycle()释放内存,然后才它设置为null.虽然recycle()从源码上看,调用它应该能立即释放Bitmap的主要内存,但是测试结果显示它并没能立即释放内存。但是我它应该还是能大大的加速Bitmap的主要内存的释放。

oom如何解决和预防

尽量提高自己的免疫力,然后不断的锻炼身体,这样的话对于预防来说是有很好的疗效。但是我们还需要掌握一定的方式方法。

如何解决上传多张图片时遇到的oom问题

一、OOM问题出现的场景和原因一个好的app总少不了精美的图片,所以Android开发中图片的加载总是避免不了的,而在加载图片过程中,如果处理不当则会出现OOM的问题。那么如何彻底解决这个问题呢?本文将具体介绍这方面的知识。首先我们来总结一下,在加载图片过程中出现的OOM的场景无非就这么几种:1、 加载的图片过大2、 一次加载的图片过多3、 以上两种情况兼有那么为什么在以上场景下会出现OOM问题呢?实际上在API文档中有着明确的说明,出现OMM的主要原因有两点:1、移动设备会限制每个app所能够使用的内存,最小为16M,有的设备分配的会更多,如24、32M、64M等等不一,总之会有限制,不会让你无限制的使用。2、在andorid中图片加载到内存中是以位图的方式存储的,在android2.3之后默认情况下使用ARGB_8888,这种方式下每个像素要使用4各字节来存储。所以加载图片是会占用大量的内存。场景和原因我们都分析完了,下面我们来看看如何解决这些问题。二、解决大图加载问题首先先来解决大图加载的问题,一般在实际应用中展示图片时,因屏幕尺寸及布局显示的原因,我们没有必要加载原始大图,只需要按照比例采样缩放即可。这样即节省内存又能保证图片不失真,具体实施步骤如下:1、在不加载图片内容的基础上,去解码图片得到图片的尺寸信息这里需要用的BitmapFactory的decode系列方法和BitmapFactory.Options。当使用decode系列方法加载图片时,一定要将Options的inJustDecodeBounds属性设置为true。BitmapFactory.Options ptions = new BitmapFactory.Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeFile(path, options);2、根据获取的图片的尺寸和要展示在界面的尺寸计算缩放比例。public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height reqHeight || width reqWidth) { if (width height) { inSampleSize = Math.round((float) height / (float) reqHeight); } else { inSampleSize = Math.round((float) width / (float) reqWidth); } } return inSampleSize; }3、根据计算的比例缩放图片。//计算图片的缩放比例 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; Bitmap bitmap= BitmapFactory.decodeFile(path, options);根据缩放比例,会比原始大图节省很多内存,效果图如下:三、批量加载大图下面我们看看如何批量加载大图,首先第一步还是我们上面所讲到的,要根据界面展示图片控件的大小来确定图片的缩放比例。在此我们使用gridview加载本地图片为例,具体步骤如下:1、通过系统提供的contentprovider加载外部存储器中的所有图片地址private void loadPhotoPaths(){ Cursor cursor= getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null); while(cursor.moveToNext()){ String path = cursor.getString(cursor.getColumnIndex(MediaColumns.DATA)); paths.add(path); } cursor.close(); }2、自定义adapter,在adapter的getview方法中加载图片@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder=null; if(convertView==null){ convertView = LayoutInflater.from(this.mContext).inflate(R.layout.grid_item_layout, null); holder = new ViewHolder(); holder.photo=(ImageView)convertView.findViewById(R.id.photo); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } final String path = this.paths.get(position); holder.photo.setImageBitmap(imageLoader.getBitmapFromCache(path)); return convertView; }通过以上关键两个步骤后,我们发现程序运行后,用户体验特别差,半天没有反应,很明显这是因为我们在主线程中加载大量的图片,这是不合适的。在这里我们要将图片的加载工作放到子线程中进行,改造自定义的ImageLoader工具类,为其添加一个线程池对象,用来管理用于下载图片的子线程。private ExecutorService executor; private ImageLoader(Context mContxt) { super(); executor = Executors.newFixedThreadPool(3); } //加载图片的异步方法,含有回调监听 public void loadImage(final ImageView view, final String path, final int reqWidth, final int reqHeight, final onBitmapLoadedListener callback){ final Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: Bitmap bitmap = (Bitmap)msg.obj; callback.displayImage(view, bitmap); break; default: break; } } }; executor.execute(new Runnable() { @Override public void run() { Bitmap bitmap = loadBitmapInBackground(path, reqWidth, reqHeight); putBitmapInMemey(path, bitmap); Message msg = mHandler.obtainMessage(1); msg.obj = bitmap; mHandler.sendMessage(msg); } }); }通过改造后用户体验明显好多了,效果图如下:虽然效果有所提升,但是在加载过程中还存在两个比较严重的问题:1、 图片错位显示2、 当我们滑动速度过快的时候,图片加载速度过慢经过分析原因不难找出,主要是因为我们时候holder缓存了grid的item进行重用和线程池中的加载任务过多所造成的,只需要对程序稍作修改,具体如下:Adapter中:holder.photo.setImageResource(R.drawable.ic_launcher); holder.photo.setTag(path); imageLoader.loadImage(holder.photo, path, DensityUtil.dip2px(80), DensityUtil.dip2px(80), new onBitmapLoadedListener() { @Override public void displayImage(ImageView view, Bitmap bitmap) { String imagePath= view.getTag().toString(); if(imagePath.equals(path)){ view.setImageBitmap(bitmap); } } });ImageLoader中:executor.execute(new Runnable() { @Override public void run() { String key = view.getTag().toString(); if (key.equals(path)) { Bitmap bitmap = loadBitmapInBackground(path, reqWidth, reqHeight); putBitmapInMemey(path, bitmap); Message msg = mHandler.obtainMessage(1); msg.obj = bitmap; mHandler.sendMessage(msg); } } });为了获得更好的用户体验,我们还可以继续优化,即对图片进行缓存,缓存我们可以分为两个部分内存缓存磁盘缓存,本文例子加载的是本地图片所有只进行了内存缓存。对ImageLoader对象继续修改,添加LruCache对象用于缓存图片。private ImageLoader(Context mContxt) { super(); executor = Executors.newFixedThreadPool(3); //将应用的八分之一作为图片缓存 ActivityManager am=(ActivityManager)mContxt.getSystemService(Context.ACTIVITY_SERVICE); int maxSize = am.getMemoryClass()*1024*1024/8; mCache = new LruCachestring, bitmap=""(maxSize){ @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes()*value.getHeight(); } }; } //存图片到缓存 public void putBitmapInMemey(String path,Bitmap bitmap){ if(path==null) return; if(bitmap==null) return; if(getBitmapFromCache(path)==null){ this.mCache.put(path, bitmap); } } public Bitmap getBitmapFromCache(String path){ return mCache.get(path); }/string,在loadImage方法中异步加载图片前先从内存中取,具体代码请下载案例。四、总结总结一下解决加载图片出现OOM的问题主要有以下方法:1、 不要加载原始大图,根据显示控件进行比例缩放后加载其缩略图。2、 不要在主线程中加载图片,主要在listview和gridview中使用异步加载图片是要注意处理图片错位和无用线程的问题。3、 使用缓存,根据实际情况确定是否使用双缓存和缓存大小。小伙伴们看懂了嘛?想要自己测试的,可以点击下载工程运行测试哦!

C/C++程序员应该如何应对OOM

你好,1,new失败的时候抛异常,外面进行catch和拒绝2,程序判断malloc/new的返回值,为NULL就拒绝请求这两个看似完美的方案都有巨大的缺陷。1,new失败抛异常会导致C++不能正确的释放资源。除非C++程序员精心的设计每个类,并且精心的进行每次catch,这实际上是不可能的;而且常常会导致各种复杂性和不稳定。2,程序判断malloc/new的返回值,这个相对靠谱一点,但实际上也会把程序变得复杂,而且没法控制类库里面malloc/new失败之后会做什么。而且无法解决操作系统的oom_killer带来的问题。3,无法处理lazy allocation和memory overcommit。这是最致命的。正确的解决方案是什么?1,事先规划内存,像memcached、squid那样,规定自己最多用多少内存。如果要拒绝请求,在malloc之前就拒绝,永远不要碰到oom这种事情。因为oom不仅会给自己带来麻烦,还会通过oom_killer给操作系统和其他进程带去麻烦。2,信任oom_killer,相信内存不足的时候系统会给你腾出你该有的内存。(内存不足的时候malloc/new是会阻塞的等oom_killer把活儿干完的。所以,如果malloc/new失败了,那就是连oom_killer都找不出可杀的进程了)3,不要信任oom_killer,是的,这和上面是矛盾的。oom_killer拥有非常高的优先级,常常会引起swap,会造成各种意料之外的副作用。你最好永远都不要遇到它。4,在linux下要信任glibc的malloc,网上很多文章介绍说malloc碎片什么的,都是炒冷饭。如果你不明白原理和最新的进展,那么就信任malloc。实在内存分配多,就搞个mem pool。5,做好监控,和自动重启。由于oom_killer等意外的存在,监控和自动重启是必须的。另外,coredump的客观存在也要求监控和自动重启。

推发布温馨提示:

"oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)"浏览人数已经达到,如你需要查询该内容或者官方网站 的相关权重及百度收录信息,可以点击爱站网"爱站数据"站长之家网"Chinaz数据"进入;5118"进入查询更多!

以目前的网站数据参考,建议大家请以爱站数据为准,更多网站价值评估因素如:访问速度、搜索引擎收录以及百度收录索引量、用户体验等;当然要评估一个站的价值,最主要还是需要根据您自身的需求以及需要,一些确切的数据则需要找的站长进行洽谈提供,如该内容百度收录情况及官方网站的IP、PV、跳出率等!


互联网 tuifabu.com 文章内容百度收录查询
当你在网上看到oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)标题时,推发布尽可能为你提供更多关于oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)的内容及oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)文章,你还可以在百度进行oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)关键词搜索相关内容文章进行查询你想要的信息!

推发布免责声明:

你所看到的关于oom异常的原因和解决方法(如何分析android的oom,与java静态代码分析工具)内容都来源于网络,不保证外部链接及内容的一定准确性和完整性,同时,对于该外部链接的指向,不由本站实际控制,在2025-11-11 16:37:13收录时,该网页上的内容,都属于合规合法,后期网页的内容如出现违规,可以直接联系网站管理员进行删除,本站不承担任何责任。