Android:java.lang.OutOfMemoryError:无法分配 23970828 字节分配,2097152 空闲字节和 2MB 直到 OOM
Posted
技术标签:
【中文标题】Android:java.lang.OutOfMemoryError:无法分配 23970828 字节分配,2097152 空闲字节和 2MB 直到 OOM【英文标题】:Android:java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM 【发布时间】:2015-11-21 13:39:08 【问题描述】:我想在 ImageView 中显示已存储的 sd 卡中的 Bitmap 图像。运行后我的应用程序崩溃并出现 OutOfMemoryError 错误:
(java.lang.OutOfMemoryError: 无法分配 23970828 字节分配,2097152 可用字节和 2MB 直到 OOM)
我不知道也不知道为什么它内存不足。我认为我的图像尺寸非常大,所以我试图改变它。
Iterator<String> it = imageArray.iterator();
while (it.hasNext())
Object element = it.next();
String objElement = element.toString();
Log.e("objElement ", " = " + objElement);
final ImageView imageView = new ImageView (getContext());
final ProgressBar pBar = new ProgressBar(getContext(), null,
android.R.attr.progressBarStyleSmall);
imageView.setTag(it);
pBar.setTag(it);
imageView.setImageResource(R.drawable.img_placeholder);
pBar.setVisibility(View.VISIBLE);
if (objElement.endsWith(mp3_Pattern))
Log.e("Mp3 ", " ends with ");
pBar.setVisibility(View.GONE);
imageView.setImageResource(R.drawable.audio_control);
if (objElement.endsWith(png_Pattern))
Bitmap bitmap = BitmapFactory.decodeFile(objElement);
int size = Math.min(bitmap.getWidth(), bitmap.getHeight());
int x = (bitmap.getWidth() - size) / 2;
int y = (bitmap.getHeight() - size) / 2;
Bitmap bitmap_Resul = Bitmap.createBitmap(bitmap, x, y, size, size);
Log.e("bitmap_Resul "," = "+ bitmap_Resul);
if (bitmap_Resul != bitmap)
bitmap.recycle();
imageView.setImageBitmap(bitmap_Resul);
Log.e("png_Pattern ", " ends with ");
Log.e(" bitmap "," = " + bitmap);
holder.linearLayout.addView(imageView);
holder.linearLayout.addView(pBar);
日志猫信息:
08-27 14:11:15.307 1857-1857/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.tazeen.classnkk, PID: 1857
java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:812)
at android.graphics.Bitmap.createBitmap(Bitmap.java:789)
at android.graphics.Bitmap.createBitmap(Bitmap.java:709)
at android.graphics.Bitmap.createBitmap(Bitmap.java:634)
at com.example.tazeen.classnkk.AllPosts_Page$MyListAdapter.getView(AllPosts_Page.java:357)
at android.widget.AbsListView.obtainView(AbsListView.java:2347)
at android.widget.ListView.makeAndAddView(ListView.java:1864)
at android.widget.ListView.fillDown(ListView.java:698)
at android.widget.ListView.fillFromTop(ListView.java:759)
at android.widget.ListView.layoutChildren(ListView.java:1659)
at android.widget.AbsListView.onLayout(AbsListView.java:2151)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2086)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1843)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
【问题讨论】:
检查图片的像素,宽度不能超过1440,高度不能超过2560,这样就不会显示OutOfMemoryError @PankajLilan 您在哪里找到这些值 (1440 X 2560)? android文档中的任何参考资料? 另见***.com/questions/477572/… @PankajLilan 你能分享参考吗? @LCJ 你找到这背后的参考或逻辑了吗? 【参考方案1】:OutOfMemoryError 是 android 中最常见的问题,尤其是在处理位图时。当由于内存空间不足而无法分配对象并且垃圾收集器无法释放一些空间时,Java 虚拟机 (JVM) 会引发此错误。
正如 Aleksey 所说,您可以在清单文件中添加以下实体 android:hardwareAccelerated="false"
, android:largeHeap="true"
它适用于某些环境。
<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
您绝对应该阅读一些 Android 开发者概念,尤其是这里:Displaying Bitmaps Efficiently
阅读所有 5 个主题并再次重写您的代码。如果它仍然不起作用,我们将很高兴看到您在教程材料中做错了什么。
这里是 SOF 中此类错误的一些可能答案
Android: BitmapFactory.decodeStream() out of memory with a 400KB file with 2MB free heap
How to solve java.lang.OutOfMemoryError trouble in Android
Android : java.lang.OutOfMemoryError
java.lang.OutOfMemoryError
Solution for OutOfMemoryError: bitmap size exceeds VM budget
编辑:来自@cjnash 的 cmets
对于在添加此行后仍然崩溃的任何人,请尝试将图像粘贴到 res/drawable-xhdpi/ 文件夹而不是 res/drawable/ 文件夹中,这应该可以解决此问题
【讨论】:
添加后应用导航变得非常缓慢。 android:hardwareAccelerated="false" 冻结你的应用 对于在添加此行后仍然出现崩溃的任何人,请尝试将图像粘贴到 res/drawable-xhdpi/ 文件夹而不是 res/drawable/ 文件夹中,这可能会解决您的问题。 为什么建议使用 android:hardwareAccelerated="false ?这样做有什么好处? 设置 android:hardwareAccelerated="false",停止了我的应用程序的许多动画,例如阴影和高度。【参考方案2】:您是否尝试过将其添加到应用程序下的清单中? android:largeHeap="true"
?
像这样
<application
android:name=".ParaseApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:largeHeap="true" >
【讨论】:
我尝试过使用这个 android:largeHeap="true" 但得到同样的错误 在使用此链接之前尝试压缩您的图像tinyjpg.com 你也可以用这个网站压缩png【参考方案3】:对我来说,问题在于我的 .png 文件被解压缩为内存中非常大的位图,因为图像的尺寸非常大(即使文件很小)。
所以解决方法是简单地调整图像的大小:)
【讨论】:
这是正确的解决方案,因为我首先尝试了上面的解决方案,但是在应用android:hardwareAccelerated="false"
之后,布局阴影等一些动画不起作用。但是调整大小后所有问题都解决了,谢谢!为这个提示 +1!
这解决了我的问题。谢谢@petrus
这对我也有用!很好的解决方案!谢谢【参考方案4】:
实际上,您可以在清单中添加这些行 android:hardwareAccelerated="false"
, android:largeHeap="true"
它适用于某些情况,但请注意代码的其他部分可能会与此争论。
<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
【讨论】:
没有用,当使用 Bitmap.createBitmap 时它崩溃并出现同样的错误 @King 抱歉(我也花了一些时间来解决这个问题,这对我有用。但这只是其中一种方式......有很多不同的方法 android:hardwareAccelerated="false"的目的是什么? @IgorGanapolsky 来自官方文档说.. see this link【参考方案5】:这应该可以工作
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
mBitmapSampled = BitmapFactory.decodeFile(mCurrentPhotoPath,options);
【讨论】:
【参考方案6】: 在设置为 ImageView 之前调整图像大小,如下所示:
Bitmap.createScaledBitmap(_yourImageBitmap, _size, _size, false);
其中 size 是 ImageView 的实际大小。您可以通过测量达到尺寸:
imageView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
并为scaling
使用下一个尺寸imageView.getMeasuredWidth()
和imageView.getMeasuredHeight()
。
【讨论】:
我尝试过使用这个 android:largeHeap="true" 但得到同样的错误 这不一定有效的另一个例子(使用私有应用程序存储):将位图放在 res/drawable/ 中可能会产生相同的错误,但不会每次都发生。将相同的位图放入 res/drawable-xhdpi/ 将不再出现错误。所以作为一个答案,它本身是不正确的。【参考方案7】:使用 Glide Library 并将尺寸覆盖到更小的尺寸;
Glide.with(mContext).load(imgID).asBitmap().override(1080, 600).into(mImageView);
【讨论】:
【参考方案8】:我得到以下错误
"E/art: Throwing OutOfMemoryError" 分配47251468字节失败 分配 16777120 个空闲字节和 23MB 直到 OOM"
在 AndroidManifest.xml 中添加 android:largeHeap="true"
之后,我消除了所有错误
<application
android:allowBackup="true"
android:icon="@mipmap/guruji"
android:label="@string/app_name"
android:supportsRtl="true"
android:largeHeap="true"
android:theme="@style/AppTheme">
【讨论】:
【参考方案9】:我已通过将图像调整为较小的尺寸解决了这个问题。我正在使用 xamarin 形式。减小 PNG 图像的大小解决了这个问题。
【讨论】:
【参考方案10】:问题:未能分配 37748748 字节分配与 16777120 空闲字节和 17MB 直到 OOM
解决方案: 1.打开你的清单文件 2. 在应用程序标签内只需添加以下两行
android:hardwareAccelerated="false"
android:largeHeap="true"
例子:
<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:largeHeap="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
【讨论】:
【参考方案11】:我发现“drawable”文件夹中的图像会在高清手机上转换为更大的图像。例如,200k 的图像将被重新采样到更高的分辨率,例如 800k 或 32000k。我不得不自己发现这一点,迄今为止还没有看到有关此堆内存陷阱的文档。为了防止这种情况,我将所有内容都放在了一个 drawable-nodpi 文件夹中(除了基于特定设备堆在 BitmapFactory 中使用“选项”之外)。我不能让我的应用程序的大小因多个可绘制文件夹而臃肿,尤其是现在屏幕定义的范围如此之广。棘手的事情是工作室现在没有在项目视图中明确指出“drawable-nodpi”文件夹,它只显示一个“drawable”文件夹。如果您不小心,当您在工作室中将图像拖放到此文件夹时,它实际上不会被拖放到 drawable-nodpi 中:
Careful here 'backgroundtest' did not actually go to drawable-nodpi and will
be resampled higher, such as 4x or 16x of the original dimensions for high def screens.
请务必在对话框中单击 nodpi 文件夹,因为项目视图不会像以前那样单独显示所有可绘制文件夹,因此不会立即发现它出错了。在我很久以前删除它之后,Studio 在某个时候为我重新创建了香草“drawable”:
【讨论】:
developer.android.com/training/multiscreen/… 对于任何寻求有关 drawable-nohdpi 解释的人(如@Androidcoder 的回答中所引用):)【参考方案12】:这对我有用:只需将图像从 drawable 文件夹移动到 drawable-hdpi。
【讨论】:
这是什么解释?为什么这个移动有效?【参考方案13】:如果 android:largeHeap="true" 对你不起作用,那么
1:
图像压缩。我正在使用这个website
2:
将图像转换为 mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi。我正在使用这个 webiste
不要删除 android:largeHeap="true"!
【讨论】:
【参考方案14】:我也有这个问题。
与上述大多数其他人相同。 问题是由大图像引起的。
只需调整一些图像的大小, 并且无需更改任何代码。
【讨论】:
【参考方案15】:Soluton 在您的清单文件中尝试这个并使用 Glide 库
编译'com.github.bumptech.glide:glide:3.7.0'
**Use Glide Library and Override size to less size;**
if (!TextUtils.isEmpty(message.getPicture()))
Glide.with(mContext).load(message.getPicture())
.thumbnail(0.5f)
.crossFade()
.transform(new CircleTransform(mContext))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.imgProfile);
android:hardwareAccelerated="false"
android:largeHeap="true"
<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
使用这个库
compile 'com.github.bumptech.glide:glide:3.7.0'
它的工作快乐编码
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
public class CircleTransform extends BitmapTransformation
public CircleTransform(Context context)
super(context);
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight)
return circleCrop(pool, toTransform);
private static Bitmap circleCrop(BitmapPool pool, Bitmap source)
if (source == null) return null;
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
// TODO this could be acquired from the pool too
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
if (result == null)
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
return result;
@Override
public String getId()
return getClass().getName();
【讨论】:
【参考方案16】:您的应用程序崩溃,因为您的图像大小(以 MB 或 KB 为单位)太大,因此它没有为此分配空间。因此,在将图像粘贴到可绘制对象之前,只需减小尺寸即可。
或
您可以在 Manifest.xml 的应用程序标签中添加以下内容
android:hardwareAccelerated="false"
android:largeHeap="true"
android:allowBackup="true"
添加此应用后不会崩溃。
始终在应用中使用较小尺寸的图片。 如果您在应用中添加大尺寸的图片,您应该添加上面的语法,但应用大小会增加。【讨论】:
【参考方案17】:将此添加到应用程序下的清单中? android:largeHeap="true"
【讨论】:
还有一种解决方法:改变height = height*.75 and width = width*.75。【参考方案18】:在某些情况下(例如循环中的操作)垃圾收集器比您的代码慢。您可以使用helper method from this answer 来等待垃圾收集器。
【讨论】:
【参考方案19】:您必须更改可绘制对象的大小。安卓显示太大了。例如如果您正在设置图像,请尝试使用较少像素的图像。这个对我有用。 谢谢。 :)
【讨论】:
【参考方案20】:添加后我的问题解决了
dexOptions
incremental true
javaMaxHeapSize "4g"
preDexLibraries true
dexInProcess = true
在 Build.Gradle 文件中
【讨论】:
这只会让你的应用在内存使用方面真的很臃肿 @cricket_007 如果有的话会有什么后果?【参考方案21】:Last but not the least....
Try Method One:
Simple Add these lines of code in the gradle file
dexOptions
incremental true
javaMaxHeapSize "4g"
Example:
android
compileSdkVersion XX
buildToolsVersion "28.X.X"
defaultConfig
applicationId "com.example.xxxxx"
minSdkVersion 14
targetSdkVersion 19
dexOptions
incremental true
javaMaxHeapSize "4g"
*******************************************************************
Method Two:
Add these two lines of code in manifest file...
android:hardwareAccelerated="false"
android:largeHeap="true"
Example:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:hardwareAccelerated="false"
android:largeHeap="true"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
It will Work for sure any of these cases.....
【讨论】:
【参考方案22】:我真的不建议像这样编辑清单
android:hardwareAccelerated="false" , android:largeHeap="true"
这些选项会导致您的应用出现不流畅的动画效果。此外,“liveData”或更改您的本地数据库(Sqlite,Room)激活缓慢。这对用户体验很不利。
所以我推荐 RESIZE bitmap
下面是示例代码
fun resizeBitmap(source: Bitmap): Bitmap
val maxResolution = 1000 //edit 'maxResolution' to fit your need
val width = source.width
val height = source.height
var newWidth = width
var newHeight = height
val rate: Float
if (width > height)
if (maxResolution < width)
rate = maxResolution / width.toFloat()
newHeight = (height * rate).toInt()
newWidth = maxResolution
else
if (maxResolution < height)
rate = maxResolution / height.toFloat()
newWidth = (width * rate).toInt()
newHeight = maxResolution
return Bitmap.createScaledBitmap(source, newWidth, newHeight, true)
【讨论】:
【参考方案23】:我是 android 开发的新手,但我希望我的解决方案有所帮助,它完美地适用于我的情况。我使用 Imageview 并将其背景设置为“src”,因为我试图制作帧动画。我遇到了同样的错误,但是当我尝试对此进行编码时,它起作用了
int ImageID = this.Resources.GetIdentifier(questionPlay[index].Image.ToLower(), "anim", PackageName);
imgView.SetImageResource(ImageID);
AnimationDrawable animation = (AnimationDrawable)imgView.Drawable;
animation.Start();
animation.Dispose();
【讨论】:
【参考方案24】:Bitmap image =((BitmapDrawable)imageView1.getDrawable()).getBitmap();
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,50/100,byteArrayOutputStream);
50/100 如果使用 100,则原始分辨率可能会因内存不足而停止应用程序。
如果 50 或小于 100,这将是 50% 或小于 100 的分辨率,这样可以防止内存不足问题
【讨论】:
【参考方案25】:使用像Picasso 或Glide 这样的图像加载库。使用这些库可以防止将来发生崩溃。
【讨论】:
【参考方案26】:使android:hardwareAccelerated="false"
成为特定于活动的。希望这可以解决冻结问题和动画问题。像这样……
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true">
.
.
.
.
<activity android:name=".NavigationItemsFolder.GridsMenuActivityClasses.WebsiteActivity"
android:windowSoftInputMode="adjustPan"
android:hardwareAccelerated="false"/>
</application>
【讨论】:
【参考方案27】:如果上传图片,请尝试降低图片质量,这是Bitmap的第二个参数。这是我的解决方案。以前是 90,然后我尝试了 60(就像现在在下面的代码中一样)。
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
finalBitmap.compress(Bitmap.CompressFormat.JPEG,60,baos);
byte[] b = baos.toByteArray();
【讨论】:
【参考方案28】:试试最简单的。也许您的应用程序崩溃了,因为您的图像大小(以 MB 为单位)太大,所以它没有为此分配空间。因此,在将图像粘贴到 drawable 之前,只需通过任何查看器软件减小大小,或者如果您在运行时从图库中获取图像,而不是在保存图像之前压缩您的位图。 它对我有用。你肯定会的。
【讨论】:
【参考方案29】:当我在继续一项新活动时没有终止我的旧活动时,我遇到了这个问题。我用finish();
修复了它
Intent goToMain = new Intent(this,MainActivity.class);
startActivity(goToMain);
finish();
【讨论】:
【参考方案30】:stream = activity.getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
bitmap = BitmapFactory.decodeStream(stream, null, options);
int Height = bitmap.getHeight();
int Width = bitmap.getWidth();
enter code here
int newHeight = 1000;
float scaleFactor = ((float) newHeight) / Height;
float newWidth = Width * scaleFactor;
float scaleWidth = scaleFactor;
float scaleHeight = scaleFactor;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
resizedBitmap= Bitmap.createBitmap(bitmap, 0, 0,Width, Height, matrix, true);
bitmap.recycle();
然后在Appliaction标签中,添加largeheapsize="true
【讨论】:
以上是关于Android:java.lang.OutOfMemoryError:无法分配 23970828 字节分配,2097152 空闲字节和 2MB 直到 OOM的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )
Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )