Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T
Accepted Solution

Memory leak in paintBackground

Hello everyone,

 I write a simple app, and move from my splash screen to menu screen. In MenuScreen class I have a paintBackground method to draw background image. Recently I noticed  severe memory leak in this method:

 

 

         VerticalFieldManager vf = new VerticalFieldManager(VerticalFieldManager.USE_ALL_WIDTH | 
         VerticalFieldManager.USE_ALL_HEIGHT | VerticalFieldManager.NO_VERTICAL_SCROLL | 
         VerticalFieldManager.NO_VERTICAL_SCROLLBAR) {
        	            
       public void paintBackground(Graphics graphics) {
        graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), bg_img, 0, 0);
        // System.out.println("=========================");
        super.paintBackground(graphics);
        	      
        	 }    
         }; 

  If I remove comments on println, it will echo infinitely. I checked, class is created once, so there shouldn't be loop of creating many instances of MenuClass.

Does anyone know what may cause such a behavior?

 

Please use plain text.
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T

Re: Memory leak in paintBackground

Short notice - it actually draws everything, but with this memory leak.
Please use plain text.
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T

Re: Memory leak in paintBackground

So far nobody has answered, and that's the answer I found by occasion.

Some notes:

SplashScreen which invoked MenuScreen was closed, only 1 screen was in stack.

 

Here is the soulution: just replace paintBackground with paint method:

 

 

public void paint(Graphics graphics) {
        	      graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), bg_img, 0, 0);
        	       System.out.println("=========================");
        	      super.paintBackground(graphics);
        	      
        	 }    
         };        

   That's it, now it will echo "===============" only once!

 

 

Please use plain text.
Developer
SamuelD
Posts: 166
Registered: ‎01-14-2009
My Device: Curve 8330

Re: Memory leak in paintBackground

Hello,
just a quick comment. You should not call paintBackground inside your paint method. The paintBackground method is called from the framework. Also, have you tried to do super.paintBackground before trying to paint your bitmap? The reason I ask is because I think that there is a clear that happen in the default paintBackground.
Thank you, have a nice day.

--
Samuel D.
Please use plain text.
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T

Re: Memory leak in paintBackground

Thanx for replying, I just tried new way:

public void paintBackground(Graphics graphics) {
            	  super.paintBackground(graphics);
            	   graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), bg_img, 0, 0);
        	       System.out.println("=========================");
        	      
        	 }

 and it loops heavily. BTW, now I don't use this way of rendering background image at all, but use setBackground  method. I profiled this chunk several times, results say no memory leak, but something tells me its still here.

Please use plain text.
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T

Re: Memory leak in paintBackground

Also one question: how comes when I print out:

System.out.println("=============>Number of Screens: "+UiApplication.getUiApplication().getScreenCount());

 it returns 0? I'm still able to see my screen rendered and running. I closed previous screen using popScreen() method.

Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: Memory leak in paintBackground

As previously noted, paintBackground is called by the framework (FYI I believe it is usually done as part of the standard paint method) and should not be invoked by your code.  If you are seeing it invoked repeatedly, then I can only assume that you are repeatedly invoking it in some way, possibly by some processing you are doing that is actually invoking the paint method (repeated invalidates, constantly updating the screen and the like). But put a break point in there, and see what the stack trace tells you, that should give you a good clue as to why this is being used repeatedly.

 

Also, having looked at your original code, I can't see how it, by itself, is causing a memory leak.  Why do you think that it actually is?

 

With respect to this question:

why is UiApplication.getUiApplication().getScreenCount()) == 0?

Sorry I have no idea.  Where are you actually invoking this?

 

 

BTW, not sure what happens here:

graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), bg_img, 0, 0);

if you Bitmap is not getWidth() * getHeight() at least. 

Please use plain text.
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T

Re: Memory leak in paintBackground

Thank you for replying! I'm gonna try to implement your tips soon. Actually, I thought that it was *memory leak* seeing infinitely printed "===================" and my simulator was almost *shaking* 'cos of crazy frequency screen repainting. Now I use seBackground code for VerticalManager with buttons, but this shaking tells me something is going wrong, though I don't trace out "===============" now.

Regarding UiApplication.getUiApplication().getScreenCount()) == 0: I have 2 screens, namely SplashScreen and MenuScreen, and switch from one to another. So I called popScreen() in SplashScreen and pushed MenuScreen. Now I use geScreen.close() and it returns 1 active screen (which seems normal in my opinion).

Please use plain text.
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T

Re: Memory leak in paintBackground

Ok, now I'm 100% sure there is a loop. Somehow when I overwrite paint() method in VerticalFieldManager it gets called by MenuScreen, which is very strange for me. Take a look at code and screenshots I made, please:

 

import net.rim.blackberry.api.browser.Browser;
import net.rim.blackberry.api.browser.BrowserSession;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Characters;
import net.rim.device.api.system.KeyListener;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;

public class MainMenu extends MainScreen {
	
	
    //Buttons of Main menu
    Bitmap newbtn_img;
    Bitmap continuebtn_img;
    Bitmap tutorialbtn_img;
    Bitmap morebtn_img;
    Bitmap bg_img;
    
    //Images for the buttons of Main menu
    BitmapField newbtn;
    BitmapField continuebtn;
    BitmapField tutorialbtn;
    BitmapField morebtn;
    
    Background bg;
    
 
    public MainMenu() {
    	super(NO_VERTICAL_SCROLL);
        //I call this to double-check previous screen was closed properly; it prints out 1
    	System.out.println("0000000000000000000000000000>Number of Screens: "+UiApplication.getUiApplication().getScreenCount());
    	bg_img = Bitmap.getBitmapResource("menu_screen.png");
    	//newbtn_img = Bitmap.getBitmapResource("new_game.png");
    	//continuebtn_img = Bitmap.getBitmapResource("tutorial.png");
    	//tutorialbtn_img = Bitmap.getBitmapResource("tutorial.png");
    	//morebtn_img = Bitmap.getBitmapResource("more_games.png");
    	//bg = BackgroundFactory.createBitmapBackground(bg_img);
    	        
        
         VerticalFieldManager vf = new VerticalFieldManager(VerticalFieldManager.USE_ALL_WIDTH | 
         VerticalFieldManager.USE_ALL_HEIGHT | VerticalFieldManager.NO_VERTICAL_SCROLL | 
         VerticalFieldManager.NO_VERTICAL_SCROLLBAR) {       	 
             public void paint(Graphics graphics) {
            	   graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), bg_img, 0, 0);
        	       System.out.println("========================="); //BREAKPOINT HERE
        	       super.paint(graphics);
        	 }
        	
         };
        
         //vf.setBackground(bg);	   	
        	     //   vf.add(newbtn);
        	     //   vf.add(continuebtn);
        	     //   vf.add(tutorialbtn);
        	     //   vf.add(morebtn);
        	        add(vf);
    }
}

  There are a few buttons in original, they for sure safe and don't cause any problems. I decided to remove them for now for better overview of real problem. 

Now, what I get in console:

 

Clip.jpg

 

And what I get from the debugger window:

Clip_2.jpg

 

When I press F8 it returns me this MainMenu.paint() infinitely.

Please use plain text.
Super Contributor
tolmachevroman
Posts: 257
Registered: ‎05-05-2011
My Device: 9700
My Carrier: AT&T

Re: Memory leak in paintBackground

UPD: Actually, I commented here addition of buttons while I myself test with them added. Few minutes ago just for curiosity I commented them in my code and voila - loop disappeared. Now, how comes addition of fields toggles severe loop??
Please use plain text.