Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是什么导致此Java代码中出现内存泄漏_Java_Android_Memory Leaks_Drawable - Fatal编程技术网

是什么导致此Java代码中出现内存泄漏

是什么导致此Java代码中出现内存泄漏,java,android,memory-leaks,drawable,Java,Android,Memory Leaks,Drawable,我写了一个方法,以调整可绘图的大小,但我发现它泄漏。它是在我的游戏的单人游戏活动中实现的,因此当我重新启动该活动(再次播放按钮)时,可用的堆大小将减小,直到它最终崩溃。我想关闭一个活动,但没有留下任何痕迹。我确信ResizeDrawable方法是唯一导致崩溃的方法,因为当我删除它时,问题就解决了。代码如下: //They don't have to be global, I guess it makes no difference Bitmap temp; Bitmap resbit; Dra

我写了一个方法,以调整可绘图的大小,但我发现它泄漏。它是在我的游戏的单人游戏活动中实现的,因此当我重新启动该活动(再次播放按钮)时,可用的堆大小将减小,直到它最终崩溃。我想关闭一个活动,但没有留下任何痕迹。我确信ResizeDrawable方法是唯一导致崩溃的方法,因为当我删除它时,问题就解决了。代码如下:

 //They don't have to be global, I guess it makes no difference
Bitmap temp;
Bitmap resbit;
Drawable resized;

Drawable ResizeDrawable(Drawable image,int width,int height) 
{
    temp = ((BitmapDrawable)image).getBitmap();
    resbit = Bitmap.createScaledBitmap(temp, width, height, true);
    resized = new BitmapDrawable(getResources(), resbit ); 
    return resized;
}
那么,为什么这会填满内存?我如何修改此方法或整个活动,以便在活动关闭后释放所有内存

更新:

我尝试使用recycle()方法。据我所知,循环使用可以释放位图的内存,这样它就可以再次使用而不会泄漏。我添加了以下几行:

            if (temp != null) 
        {
            temp.recycle();
            temp = null;
        }
        if (resbit != null) 
        {
            resbit .recycle();
            resbit  = null;
        }
1) 在使用可调尺寸拉伸方法时 2) 返回前语句

两次编辑都导致“尝试使用回收的位图”崩溃。我哪里出错了

更新:

我试图删除“重新比特回收”部分。现在我可以重新启动我的活动整整2次,然后它崩溃了,出现了相同的异常。这怎么可能

更新:

我尝试用以下命令覆盖OnDestroy():

以及:

没有什么变化。还尝试使用循环覆盖OnDestroy()。同样的“整整两次”崩溃

日志:

因此,在SinglePlayer活动重新启动16次之后,原始代码崩溃。日志:

11-16 03:46:31.115: E/AndroidRuntime(9649): FATAL EXCEPTION: main
11-16 03:46:31.115: E/AndroidRuntime(9649): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.starena/com.example.starena.SinglePlayer}: android.view.InflateException: Binary XML file line #40: Error inflating class <unknown>
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1659)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1675)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.ActivityThread.access$1500(ActivityThread.java:121)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:943)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.os.Looper.loop(Looper.java:130)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.ActivityThread.main(ActivityThread.java:3701)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at java.lang.reflect.Method.invokeNative(Native Method)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at java.lang.reflect.Method.invoke(Method.java:507)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at dalvik.system.NativeStart.main(Native Method)
11-16 03:46:31.115: E/AndroidRuntime(9649): Caused by: android.view.InflateException: Binary XML file line #40: Error inflating class <unknown>
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.view.LayoutInflater.createView(LayoutInflater.java:518)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:568)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:227)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.Activity.setContentView(Activity.java:1657)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at com.example.starena.SinglePlayer.onCreate(SinglePlayer.java:177)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1623)
11-16 03:46:31.115: E/AndroidRuntime(9649):     ... 11 more
11-16 03:46:31.115: E/AndroidRuntime(9649): Caused by: java.lang.reflect.InvocationTargetException
11-16 03:46:31.115: E/AndroidRuntime(9649):     at java.lang.reflect.Constructor.constructNative(Native Method)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at java.lang.reflect.Constructor.newInstance(Constructor.java:415)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.view.LayoutInflater.createView(LayoutInflater.java:505)
11-16 03:46:31.115: E/AndroidRuntime(9649):     ... 22 more
11-16 03:46:31.115: E/AndroidRuntime(9649): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:494)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:370)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:715)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.content.res.Resources.loadDrawable(Resources.java:1720)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.widget.ImageView.<init>(ImageView.java:122)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.widget.ImageButton.<init>(ImageButton.java:85)
11-16 03:46:31.115: E/AndroidRuntime(9649):     at android.widget.ImageButton.<init>(ImageButton.java:81)
11-16 03:46:31.115: E/AndroidRuntime(9649):     ... 25 more
此外,每个图像按钮都有两个可绘制项,我通过OnClick()方法在它们之间交替切换(我只是一个或另一个地设置ImageDrawable()

我希望这有帮助

已解决: 我不得不在OnDestroy上写下:

Runtime.getRuntime().gc(); 
Drawable1 = null;
ImgButton1.setImageDrawable(null);
当然,我对每一对(ImgButton,Drawable)都这样做,这样就不再消耗内存了。我没有回收位图。

尝试调用Bitmap.recycle()以查找未使用的位图实例

位图.recycle()

您是指堆栈大小,还是指堆大小?另外,向我们展示异常及其完整跟踪。当然,向我们展示。另外,顺便说一句,如果堆空间不足,那么堆空间也就不足了,并且运行GC的任何强制(从技术上讲,只是“建议”)都不会改变这一点——它会自动运行。向我们展示如何使用
ResizeDrawable
。您是否保留了对它返回的
Drawable
的未使用引用(防止GC丢弃旧的未使用对象)?也许
Runtime.freemory()
的战略性打印输出将帮助您追踪罪魁祸首?除了保留未使用的引用之外:仔细看,这可能很棘手。也许您将
Drawable
存储为某个类的成员字段,您可以将该类注册为某个事件处理程序,或者存储在列表中,或者存储在某个地方的另一个字段中。查看您存储对该
可绘制的
的引用的每个位置,仔细考虑是否不必要地保留引用。也许明智地重置为
null
或在适当的时候使用
WeakReference
s可能是一个解决方案。顺便说一句,您写道“两次编辑都导致“尝试使用回收的位图”崩溃。我哪里出错了?”。这意味着,在你认为你已经使用完这些可绘制图形之后,它们仍然在某个地方被使用,这也证明了引用是无意中保留的。关键是,如果您在认为已使用完位图的时候回收了位图,但在使用回收的位图时仍然出现错误,那么您正在创建的其中一个对象在您认为已使用完位图后仍在使用。因此,这意味着,您不知道的是,某些东西持有对您认为已经处理过的对象的引用,从而阻止它们被GC’d<代码>已调整大小
包含对
resbit
的引用,这也可能包含对
temp
的引用,具体取决于其内部实现方式。
Drawable1 = context.getResources().getDrawable(R.drawable.drawable1);   
Drawable1 = ResizeDrawable(Drawable1,ButtonWidth,ButtonHeight);
ImgButton1 = (ImageButton) findViewById(R.id.ImageButton02);
ImgButton1.setOnClickListener(this);
ImgButton1.setImageDrawable(Drawable1);
Drawable1 = null;
ImgButton1.setImageDrawable(null);