android基础GLSurfaceView内存泄漏

android基础GLSurfaceView内存泄漏,android,multithreading,opengl-es,memory-leaks,glsurfaceview,Android,Multithreading,Opengl Es,Memory Leaks,Glsurfaceview,我从一些OpenGL/Android教程中拼凑了一个我称之为“ViewManager”的东西。问题是我有内存泄漏。我每隔一段时间就会收到一次GC通知,我认为我什么也没做 11-23 01:50:34.435:D/dalvikvm(954):GC_并发释放381K,6%释放8024K/8519K,暂停18ms+6ms,总计64ms 我的代码首先扩展GLSurfaceView并实现回调和Runnable。然后我创建并启动了一个gameLoop,它负责更新对象 正如您从我的代码中看到的,我的列表中还没

我从一些OpenGL/Android教程中拼凑了一个我称之为“ViewManager”的东西。问题是我有内存泄漏。我每隔一段时间就会收到一次GC通知,我认为我什么也没做

11-23 01:50:34.435:D/dalvikvm(954):GC_并发释放381K,6%释放8024K/8519K,暂停18ms+6ms,总计64ms

我的代码首先扩展GLSurfaceView并实现回调和Runnable。然后我创建并启动了一个gameLoop,它负责更新对象

正如您从我的代码中看到的,我的列表中还没有任何对象,因此泄漏不会发生在对象的
.draw
.update
方法中

我在运行代码时取出了gameLoop,内存泄漏似乎停止了。有人对我为什么会收到内存泄漏有任何提示吗?另一方面,当我删除run方法上的
Thread.sleep(30)
调用时,我得到GC\u并发通知的速度要快很多倍

import java.util.LinkedList;
import java.util.ListIterator;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.view.MotionEvent;


public class ViewManager extends GLSurfaceView implements Runnable, GLSurfaceView.Renderer
{
    private Camera camera;
    private ListIterator<GameObject> objIterator;
    private LinkedList<GameObject> objects;
    private Thread gameThread;
    private boolean running;

    public ViewManager(Context context)
    {
        super(context);
        setRenderer(this);

        objects = new LinkedList<GameObject>();

        camera = new Camera();
        camera.setPosZ(-4.0f);

    }

    public void onDrawFrame(GL10 gl)
    {
        gl.glClear(GL10.GL_DEPTH_BUFFER_BIT|GL10.GL_COLOR_BUFFER_BIT);

        //3D Drawing
        objIterator = objects.listIterator();
        gl.glLoadIdentity();
        camera.draw(gl);    
        while(objIterator.hasNext())
        {
            gl.glPushMatrix();
            objIterator.next().draw(gl);
            gl.glPopMatrix();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        if(event.getAction() == MotionEvent.ACTION_DOWN)
        {
            camera.getPreviouslyTouchedPoint().set((int)event.getX(),(int)event.getY());
        }

        if(event.getAction() == MotionEvent.ACTION_MOVE)
        {
            camera.setPosX(camera.getPosX() - (camera.getPreviouslyTouchedPoint().x-event.getX())/100f);
            camera.setPosY(camera.getPosY() - (camera.getPreviouslyTouchedPoint().y-event.getY())/100f);
        }

        camera.getPreviouslyTouchedPoint().set((int)event.getX(),(int)event.getY());

        return true;
    }
    public void onSurfaceChanged(GL10 gl, int width, int height)
    {
        running = false;

        gl.glViewport(0,0,width,height);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        GLU.gluPerspective(gl, 45.0f, (float)width/(float)height,0.1f,100.0f);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();

        running = true;
        gameThread = new Thread(this);
        gameThread.start();
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig arg1)
    {
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glClearDepthf(1.0f);
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glDepthFunc(GL10.GL_LEQUAL);
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    }

    public void run()
    {
        ListIterator<GameObject> itr = objects.listIterator();

        while(running)
        {
            itr = objects.listIterator();
            while(itr.hasNext())
            {
                itr.next().update(0);
            }
            try
            {
                Thread.sleep(30);
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
import java.util.LinkedList;
导入java.util.ListIterator;
导入javax.microedition.khronos.egl.EGLConfig;
导入javax.microedition.khronos.opengles.GL10;
导入android.content.Context;
导入android.opengl.GLSurfaceView;
导入android.opengl.GLU;
导入android.view.MotionEvent;
公共类ViewManager扩展了GLSURFACHEVIEW实现了可运行的GLSURFACHEVIEW.Renderer
{
私人摄像机;
私有列表迭代器;
私有LinkedList对象;
私有线程;
私有布尔运行;
公共视图管理器(上下文)
{
超级(上下文);
(本),;
对象=新的LinkedList();
摄像头=新摄像头();
摄像头。setPosZ(-4.0f);
}
公共框架(GL10 gl)
{
gl.glClear(GL10.gl_深度_缓冲_位| GL10.gl_颜色_缓冲_位);
//三维绘图
objIterator=objects.listIterator();
gl.glLoadIdentity();
照相机.绘图(gl);
while(objIterator.hasNext())
{
gl.glPushMatrix();
objIterator.next().draw(gl);
gl.glPopMatrix();
}
}
@凌驾
公共布尔onTouchEvent(运动事件)
{
if(event.getAction()==MotionEvent.ACTION\u向下)
{
camera.getPreviouslyTouchedPoint().set((int)event.getX(),(int)event.getY());
}
if(event.getAction()==MotionEvent.ACTION\u MOVE)
{
camera.setPosX(camera.getPosX()-(camera.getPreviouslyTouchedPoint().x-event.getX())/100f);
camera.setPosY(camera.getPosY()-(camera.getPreviouslyTouchedPoint().y-event.getY())/100f);
}
camera.getPreviouslyTouchedPoint().set((int)event.getX(),(int)event.getY());
返回true;
}
表面上的公共空隙已更改(GL10 gl,整型宽度,整型高度)
{
运行=错误;
gl.glViewport(0,0,宽度,高度);
gl.glMatrixMode(GL10.gl_投影);
gl.glLoadIdentity();
GLU.GLU透视图(gl,45.0f,(浮动)宽度/(浮动)高度,0.1f,100.0f);
gl.glMatrixMode(GL10.gl_MODELVIEW);
gl.glLoadIdentity();
运行=真;
gameThread=新线程(此线程);
gamesthread.start();
}
已创建曲面上的公共void(GL10 gl、EGLConfig arg1)
{
gl.glShadeModel(GL10.glu平滑);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.gl_深度_试验);
gl.glDepthFunc(GL10.gl_LEQUAL);
gl.glHint(GL10.gl\u透视图\u校正\u提示,GL10.gl\u最佳);
}
公开募捐
{
ListIterator itr=objects.ListIterator();
(跑步时)
{
itr=objects.listIterator();
while(itr.hasNext())
{
itr.next().update(0);
}
尝试
{
睡眠(30);
}捕捉(中断异常e)
{
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}
}

内存泄漏和正在运行的GC之间总是存在混淆(尽管它们几乎是相反的情况)。当存在对阻止GC收集这些对象的对象的引用时,就会发生内存泄漏。GC收集不再被任何活动线程引用的对象(这是
ListIterator
对象的情况)

一旦线程完成,任何活动线程都不再引用您的
ListIterator
,因此GC将收集它


要防止GC运行,请在线程退出之前删除引用(在
run()
方法中),在
run()
方法末尾使用此对象,或者使用每次重用的类级
Iterator
对象(不在每次线程运行时创建新对象).

看来,仅仅创建迭代器就是问题的根源。我注释掉了迭代器的内容,但离开了循环,这就是内存泄漏发生的地方。我编写了自己的简单链表和节点迭代方法,现在运行它时没有内存泄漏,这让我真的认为listIterator()方法有内存泄漏!(或者我用错了)非常非常有趣…你怎么知道你有内存泄漏?GC运行并不意味着你有漏洞(事实上恰恰相反)嗯,好问题,我想可能不是漏洞,但我不明白的是为什么调用LinkedList.listIterator()会导致调用GC。当我迭代我的自定义链表时,GC永远不会被调用。这是有道理的。所以循环的每一次迭代我都会创建一个新的对一个新迭代器的引用,而旧迭代器留给GC。我的问题是,我如何将当前迭代器“重置”回LinkedList的开头?我知道的唯一方法是调用“.listIterator”方法。P.S.I.h