Search code examples
javaarraylistmemory-leaksjavacv

Adding a new object to ArrayList is causing memory leak?


Whenever I try to add a new Question to an ArrayList of Question, it leaks memory. Inside the constructor of the Question class I create five new Rectangle Objects. The interesting thing is that when I comment out the five new Rectangles in my constructor of Question class, the native memory stops leaking by at least 400 megabytes. When I run the JProfiler, the heap size remains consistent but the task manager is showing over 700 MegaByte of memory being used.

Here is the constructor of the Question Class

public Question(int number,int options,IplImage in,String imgname,int unit,Point orig, JsonArray cells, JsonArray rows, int avgr) throws CellsWrongDetection{
    nu  = number;
    this.imgname = imgname;
    totOpt  = options;
    this.cells = cells;
    this.rows = rows;
    this.avgr = avgr;
    optA = new Rectangle(in);
    optB = new Rectangle(in);
    optC = new Rectangle(in);
    optD = new Rectangle(in);
    optE = new Rectangle(in);
    optF = new Rectangle(in);
    tmpimgx = in;
    setoptloc();
    //drawmaps();
}

Here is where I add a Question in the ArrayList

public void addAllQuestions(int[] options,String imgname) throws CellsWrongDetection{
    for (int i = 0; i < total; i++) {
        Question q=new Question(i, options[i], image, imgname, unit, orig, cells, rows, avgr);
        questions.add(q);

    }

}

Here is The Rectangle Class

public class Rectangle extends Config{
private IplImage in;
public CvPoint tl,br;
public Rectangle(IplImage in){
    this.in = in;

}
public Rectangle()
{

}


public boolean isBlack(){
    double b=0,w=0;
    for (int y = tl.y(); y < br.y(); y++) {
        for (int x = tl.x(); x < br.x(); x++) {
            if (isblackp(x,y)) b++;
            else w++;
        }
    }
    double per = (b/w)*100 ;
    return (per <= percent)?false:true;
}
/***
 * Setting Edges points
 * @param p1 top-left corner
 * @param p2 bottom-right corner
 */
public void setCorn(CvPoint p1, CvPoint p2) {
    tl = p1;
    br = p2;
}
public void setCorn(int x0,int y0,int x1,int y1){
    //System.out.println("Setting points x0= "+x0+",y0="+y0+",x1= "+x1+",y1="+y1);
    CvPoint p1 = new CvPoint(),
            p2 = new CvPoint();
    p1.x(x0);p1.y(y0);
    p2.x(x1);p2.y(y1);
    setCorn(p1, p2);
}
public String displayCorners(){
    return "TopLeft ("+tl.x()+","+tl.y()+") BottomRight ("+br.x()+","+br.y()+")";
}
public double getheight(){
    return br.x() - tl.x();
}
public double getwidth(){
    return br.y() - tl.y();
}
/*
 * Detecting if pixel is black
 * @return boolean
 */
public boolean isblackp(int x,int y){
    CvScalar s=cvGet2D(in,y,x);
    in.release();
    cvReleaseImage(in);
    //System.out.println( "B:"+ s.val(0) + " G:" + s.val(1) + " R:" + s.val(2));//Print values
    return (s.val(2) <= cB && s.val(0) <= cG
            && s.val(1) <= cR)?true :false;
}

} EDIT: The list gets cleared in the controller.

        for ( File file : filesInDirectory ) {

                if(isCancelled()){
                    view.dialog.setVisible(false);

                    return null;
                }

                view.SetNumerator(++index);
                String curimgname = file.getName();
                logger.log(Level.INFO,"Selected file "+curimgname);

                try {

                    sheet = new OmrModel(fh);
                    setProgress(0);


                    sheet.setpaths(curimgname, directory.toString());
                    setProgress(5);

                    sheet.init();
                    setProgress(10);


                    sheet.lookref("first");
                    setProgress(20);
                    sheet.scale();
                    sheet.lookref("second");
                    setProgress(25);
                    initDocs();
                    setProgress(30);

                    sheet.circle();
                    setProgress(40);

                    initQuestions(sheet.getQuestions(),sheet.getoptions(),sheet.getcols(),sheet.getrows(),sheet.avgr());

                    setProgress(50);

                    String[] results = sheet.getresults();
                    setProgress(60);

                    sheet.ClearQuestions();

                    sheet.drawgrid();
                    setProgress(70);

                    outcsv.println(curimgname+","+Arrays.toString(results));
                    setProgress(80);

                    genrslt(docs,sheet.getstudent(),"OMR", results);
                    setProgress(90);

                    //docs.push();
                    setProgress(100);
                    //movefile(file.getPath(),0);
                    System.gc();
                    System.out.println("Relaseing");
                    setProgress(100);
                    sheet.release();
                    publish(curimgname+"#"+sheet.getQrCode()+"#success");
                } catch (UnableToDetectOptions | WrongFileAttributes | UnableToLoadImage | UnableToDetectMarkers | MappingNotCorrect | WrongMarkers e1){
                    publish(curimgname+"#"+sheet.getQrCode()+"#"+e1.getMessage());
                    sheet.release();
                    //movefile(file.getPath(),-1);

                }

                catch (CouchDbException e2){
                    publish(curimgname+"#"+sheet.getQrCode()+"#Error Code 13");
                    //movefile(file.getPath(),-1);
                    sheet.release();
                } catch (RuntimeException e2){
                    e2.printStackTrace();
                    publish(curimgname+"#"+sheet.getQrCode()+"#Error Code 7");
                    sheet.release();
                    //movefile(file.getPath(),-1);
                } catch (CancelException | QrFailedToDetect e1){
                    publish(curimgname+"# #Error Code"+e1.getMessage());
                    //movefile(file.getPath(),1);
                    sheet.release();
                }
                catch(OutOfMemoryError e4)
                {
                    e4.printStackTrace();   
                    sheet.release();
                }


            }
            return null;

Solution

  • You are not leaking memory; the java GC effectively deallocates unreachable (unused) objects only when you are close to running out of memory; therefore you can see 1GB in the task manager even when 10 times less that that is actually being used by alive objects.