簡體   English   中英

我的應用程序崩潰是因為根據垃圾回收器,僅剩余4%的堆內存……如何防止這種情況發生?

[英]My application crashes because according to the garbage collector, only 4% heap memory is remaining… How do I prevent this?

我在Android應用程序中使用位圖,並打開GLES 2.0渲染它們。 該應用程序崩潰,釋放的日志GC_FOR_ALLOC <1K,免費的4%12240K / 12640K。我的目標是從手機/平板電腦的gallery文件夾中渲染位圖。 一切正常。 我收集所有紋理(圖像)詳細信息(必須在屏幕上進行渲染的位置以及紋理的圖像名稱= MyApplication.getTextures();紋理是一個不斷增長的數組列表。因此,在我的onDrawFrame中,我在繪制每一幀中的所有紋理。請注意,位圖來自圖庫而不是資源文件夾。這是代碼:

package com.example.hmi_abp;


import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;`
import java.nio.ShortBuffer;
import java.util.ArrayList;

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

import com.example.rendering.TextureHelper;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;
import android.opengl.Matrix;

public class GLRenderer implements Renderer {

// Our matrices
private final float[] mtrxProjection = new float[16];
private final float[] mtrxView = new float[16];
private final float[] mtrxProjectionAndView = new float[16];

// Geometric variables
public static float vertices[][];
public static short indices[][];
public FloatBuffer vertexBuffer[];
public ShortBuffer drawListBuffer[];
public static float uvs[][];
public FloatBuffer uvBuffer[];
private final Context mActivityContext;




// Our screenresolution
float   mScreenWidth = 1280;
float   mScreenHeight = 768;

// Misc
Context mContext;
int mProgram;
int number;
private ArrayList<TextureProperties> textures;
private int[] mTextureDataHandle;

public GLRenderer(Context c)
{
    mActivityContext = c;

}

public void onPause()
{
    /* Do stuff to pause the renderer */
}
public void onResume()
{



}

@Override
public synchronized void onDrawFrame(GL10 unused) {


    textures=MyApplication.getTextures();



    number = textures.size();

    System.out.println("number"+ number);

    mTextureDataHandle = new int[number];
    vertices=new float[number][12];
    uvs=new float[number][8];
    indices=new short [number][6];
    vertexBuffer = new FloatBuffer[number];
    drawListBuffer= new ShortBuffer[number];
    uvBuffer=new FloatBuffer[number];

      int k=0,h,w;
        for(;k<number;k++)
        {

            Bitmap bitmap =BitmapFactory.decodeFile(textures.get(k).name);

            h=bitmap.getHeight();
            w=bitmap.getWidth();
                                setUpBuffers(k,h,w);

              Render(mtrxProjectionAndView,k);
        }



}

private synchronized void Render(float[] m, int k) {


                mTextureDataHandle[k] = 
TextureHelper.loadTexture(mActivityContext,textures.get(k).name);

            // get handle to vertex shader's vPosition member
int mPositionHandle=GLES20.glGetAttribLocation(riGraphicTools.sp_Image,"vPosition");

            // Enable generic vertex attribute array
            GLES20.glEnableVertexAttribArray(mPositionHandle);

            // Prepare the triangle coordinate data
            GLES20.glVertexAttribPointer(mPositionHandle, 3,
                                         GLES20.GL_FLOAT, false,
                                         0, vertexBuffer[k]);

            // Get handle to texture coordinates location
            int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image,      "a_texCoord" );

            // Enable generic vertex attribute array
            GLES20.glEnableVertexAttribArray ( mTexCoordLoc );

            // Prepare the texturecoordinates
            GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
                    false,
                    0, uvBuffer[k]);

            // Get handle to shape's transformation matrix
            int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image, "uMVPMatrix");

            // Apply the projection and view transformation
            GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mtrxProjectionAndView, 0);

            // Get handle to textures locations
            int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image, "s_texture" );

            // Set the sampler texture unit to 0, where we have saved the texture.
            GLES20.glUniform1i ( mSamplerLoc, 0);
        //    System.out.println(k);
            // Draw the triangle
            GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices[k].length,
                    GLES20.GL_UNSIGNED_SHORT, drawListBuffer[k]);

            // Disable vertex array
            GLES20.glDisableVertexAttribArray(mPositionHandle);
            GLES20.glDisableVertexAttribArray(mTexCoordLoc);

}

@Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

    // We need to know the current width and height.
    mScreenWidth = width;
    mScreenHeight = height;

    // Redo the Viewport, making it fullscreen.
    GLES20.glViewport(0, 0, (int)mScreenWidth, (int)mScreenHeight);

    // Clear our matrices
    for(int i=0;i<16;i++)
    {
        mtrxProjection[i] = 0.0f;
        mtrxView[i] = 0.0f;
        mtrxProjectionAndView[i] = 0.0f;
    }

    // Setup our screen width and height for normal sprite translation.
    Matrix.orthoM(mtrxProjection, 0, 0f, mScreenWidth, 0.0f, mScreenHeight, 0, 50);

    // Set the camera position (View matrix)
    Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);

   }
   @Override
  public synchronized void onSurfaceCreated(GL10 gl, EGLConfig config) {




    // Set the clear color to black
   GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);

    // Create the shaders, solid color
    int vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_SolidColor);
    int fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_SolidColor);

    riGraphicTools.sp_SolidColor = GLES20.glCreateProgram();             // create empty OpenGL ES Program
    GLES20.glAttachShader(riGraphicTools.sp_SolidColor, vertexShader);   // add the vertex shader to program
    GLES20.glAttachShader(riGraphicTools.sp_SolidColor, fragmentShader); // add the fragment shader to program
    GLES20.glLinkProgram(riGraphicTools.sp_SolidColor);                  // creates OpenGL ES program executables

    // Create the shaders, images
    vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_Image);
    fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_Image);

    riGraphicTools.sp_Image = GLES20.glCreateProgram();             // create empty OpenGL ES Program
    GLES20.glAttachShader(riGraphicTools.sp_Image, vertexShader);   // add the vertex shader to program
    GLES20.glAttachShader(riGraphicTools.sp_Image, fragmentShader); // add the fragment shader to program
    GLES20.glLinkProgram(riGraphicTools.sp_Image);                  // creates OpenGL ES program executables

    // Set our shader programm
    GLES20.glUseProgram(riGraphicTools.sp_Image);








}

public synchronized void setUpBuffers(int k, int h, int w)
{


     // We have to create the vertices of our triangle.
    vertices[k] = new float[number*12];

        vertices[k][0]= textures.get(k).xPos;
        vertices[k][1]= textures.get(k).yPos;
        vertices[k][2]= 0.0f;
        vertices[k][3]= textures.get(k).xPos;
        vertices[k][4]= textures.get(k).yPos-h;
        vertices[k][5]= 0.0f;
        vertices[k][6]= textures.get(k).xPos+w;
        vertices[k][7]= textures.get(k).yPos-h;
        vertices[k][8]= 0.0f;
        vertices[k][9]= textures.get(k).xPos+w;
        vertices[k][10]= textures.get(k).yPos;
        vertices[k][11]= 0.0f;




    // The vertex buffer.
    ByteBuffer bb = ByteBuffer.allocateDirect(vertices[k].length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer[k] = bb.asFloatBuffer();
    vertexBuffer[k].put(vertices[k]);
    vertexBuffer[k].position(0);

    indices[k] = new short[number*6];


        indices[k][0]   = 0;//(short) (k*4);
        indices[k][1] = 1;//(short) (k*4+1);
        indices[k][2] = 2;//(short) (k*4+2);
        indices[k][3] = 0;//(short) (k*4);
        indices[k][4] = 2;//(short) (k*4+2);
        indices[k][5] = 3;//(short) (k*4+3);

    // initialize byte buffer for the draw list
    ByteBuffer dlb = ByteBuffer.allocateDirect(indices[k].length * 2);
    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer[k] = dlb.asShortBuffer();
    drawListBuffer[k].put(indices[k]);
    drawListBuffer[k].position(0);




    // Create our UV coordinates.
    uvs[k] = new float[number*8];


            uvs[k][0]=0.0f;
            uvs[k][1]=0.0f;
            uvs[k][2]=0.0f;
            uvs[k][3]=1.0f;
            uvs[k][4]=1.0f;
            uvs[k][5]=1.0f;
            uvs[k][6]=1.0f;
            uvs[k][7]=0.0f;


    // The texture buffer
    ByteBuffer bb2 = ByteBuffer.allocateDirect(uvs[k].length * 4);
    bb2.order(ByteOrder.nativeOrder());
    uvBuffer[k] = bb2.asFloatBuffer();
    uvBuffer[k].put(uvs[k]);
    uvBuffer[k].position(0);


}

 }

您應該在清單文件中使用android:largeHeap="true"來請求更大的堆大小,但這不適用於任何之前的Honeycomb設備。 在2.3版之前的設備上,您可以使用VMRuntime類,但是在Gingerbread及更高版本上將無法使用。

具有最大限制的唯一方法是通過NDK執行內存密集型任務,因為NDK不會像SDK那樣施加內存限制。

或者,您可以使用以下方法:

內存外的錯誤

使用List,LinkedList和HashMap的內存泄漏和內存不足錯誤

使用LRU緩存的內存泄漏和內存不足錯誤

使用磁盤LRU緩存的內存泄漏和內存不足錯誤

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM