Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 7 of 7

Thread: Properly releasing memory to avoid memory pileup/crash

  1. #1
    Junior Member
    Join Date
    Jul 2012
    Posts
    2
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Default Properly releasing memory to avoid memory pileup/crash

    Hi, I'm new to java, but I am working on the startings of a speed reading application... The application currently inputs a text file, displays it in a jtextpane, highlights the first sentence letter by letter in a for loop until a period is found, then truncates that sentence from the jtextpane, finally starting the highlighting process over with the next sentence as the new first sentence of the jtextpane. Every time the application restarts highlighting a sentence it paints the background of the jtextpane with an image (successively painting a new image from a list of images stored in a folder on my hard drive).

    So you kind of get an automated reading experience, that keeps highlighting and chopping off a sentence, to avoid the need for scrolling through the jtextpane, all the while repainting images behind the text in the jtextpane.

    Apparently I don't have a clue what I'm doing when it comes to allowing java to release either the graphics cache, or the image cache, or perhaps the jtextpane paint cache, because every time the application repaints the jtextpane with a new image, the memory usage goes up and the last image cache is never released from memory.

    The only image related sections of the code are: the public static declarations of (graphics g1, image img);

    27.	public static Image img;
    28.	
    29.	public static Graphics g1;

    The overridden: protected void paintComponent(Graphics g);
    176.	private static class MyTextPane extends JTextPane 
    177.	{ 
    178.  public MyTextPane() 
    179.    { 
    180.        super(); 
    181.        setText("Hello World"); 
    182.        setOpaque(false); 
    183.        setBackground(new Color(0,0,0,0)); 
    184.    } 
    185.
    186.   @Override 
    187.    protected void paintComponent(Graphics g) 
    188.    { 
    189.    if(g1 == null)
    190.    {
    191.    g1 = g;
    192.    }
    193.    img = null; 
    194.    img = Toolkit.getDefaultToolkit().getImage("C:\\images\\" + i1 + ".jpg");            
    195.    g.drawImage(img, 0, 0, this); 
    196.   super.paintComponent(g); 
    197.    }
    198. }


    and a section in the main that makes intermittent calls to the overridden paintComponent method and increments the image file name place holder
    125.	jtp.paintComponent(g1);
    126.	if(i1 < 600)
    127.	i1++;
    128.	else
    129.	i1 = 100;

    The entire 200 lines of code

    1. import java.net.MalformedURLException;
    2. import java.net.URL;
    3. import java.awt.Color;
    4. import java.awt.Dimension;
    5. import java.awt.Graphics;
    6. import java.awt.Image;
    7. import java.awt.Toolkit;
    8. import java.awt.image.BufferedImage;
    9. import java.io.File;
    10. import java.io.IOException;
    11. import javax.imageio.ImageIO;
    12. import javax.swing.ImageIcon;
    13. import javax.swing.JFileChooser;
    14. import javax.swing.JFrame;
    15. import javax.swing.JLabel;
    16. import javax.swing.JPanel;
    17. import javax.swing.JScrollPane;
    18. import javax.swing.JTextPane;
    19. import javax.swing.text.BadLocationException;
    20. import javax.swing.text.DefaultHighlighter;
    21.
    22. import org.apache.commons.io.FileUtils;
    23.
    24.
    25. public class storybook
    26. {
    27.	public static Image img;
    28.	
    29.	public static Graphics g1;
    30.	public static int i1 = 100;
    31.	
    32.	public static void main( String args[] )
    33.	{
    34.		
    35.		JFileChooser fileChooser = new JFileChooser();
    36.	      
    37.	      // show open file dialog
    38.	      int result = fileChooser.showOpenDialog( null );
    39.
    40.	      if ( result == JFileChooser.APPROVE_OPTION ) // user chose a file
    41.	      {
    42.	         URL mediaURL = null;
    43.	         
    44.	         try
    45.	         {
    46.	            // get the file as URL
    47.	            mediaURL = fileChooser.getSelectedFile().toURI().toURL();
    48.	         } // end try
    49.	         catch ( MalformedURLException malformedURLException )
    50.	         {
    51.	            System.err.println( "Could not create URL for the file" );
    52.	         } // end catch
    53.
    54.	         if ( mediaURL != null ) // only display if there is a valid URL
    55.	         {
    56.	        	 JLabel jl1 = new JLabel("Label");
    57.	        	 FileUtils fu = new FileUtils();
    58.	        	 File f = new File (mediaURL.getFile());	        	 
    59.	        	 String t = new String();
    60.	        	 try 
    61.	        	 {
    62.	        		 t = FileUtils.readFileToString(f);
    63.	        	 } 
    64.	        	 catch (IOException e) 
    65.	        	 {
    66.					// TODO Auto-generated catch block
    67.					e.printStackTrace();
    68.	        	 }
    69.	        	 JFrame jf = new JFrame("Text");
    70.	        	 JPanel jp = new JPanel();
    71.	        	 MyTextPane jtp = new MyTextPane();
    72.	        	 MyTextPane jtp2 = new MyTextPane();
    73.	        	 jtp2.setSize(1024,768);
    74.	        	 jtp.setSize(1024,768);
    75.
    76.	        	 jtp.setText(t);
    77.	        	 jtp2.setText(t);
    78.
    79.	        	 JScrollPane slider = new JScrollPane(jtp);
    80.	        	 slider.setVisible(true);
    81.	        	 slider.setPreferredSize(new Dimension(1024, 768));
    82.
    83.	        	 jp.add(slider);
    84.	        	 JPanel jp1 = new JPanel();
    85.	        	 BufferedImage myPicture = null;
    86.	        	 
    87.	        	 try 
    88.		{
    89.		myPicture = ImageIO.read(new File("C:\\Lighthouse.jpg"));
    90.		} 
    91.		catch (IOException e1) 
    92.		{
    93.		// TODO Auto-generated catch block
    94.		e1.printStackTrace();
    95.		} 
    96.	        	 
    97.	        	 jf.add(jp);
    98.	        	 jf.setSize(1024,768);
    99.	        	 jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    100.	        	 jf.setIconImage(Toolkit.getDefaultToolkit().getImage("C:\\Lighthouse.jpg"));
    101.
    102.	        	 jf.setVisible(true);
    103.	        	 
    104.	       char space;
    105.	       String periodstring = ".";
    106.	       char period = periodstring.charAt(0);
    107.	       String spacestring = " ";
    108.	       space = spacestring.charAt(0);
    109.	       int nz = 0;
    110. DefaultHighlighter.DefaultHighlightPainter highlightPainter =  new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
    111.	        	 t.replaceAll("\r", "");
    112.	        	 t.replaceAll("\n", "");
    113.	        	 
    114.	        for(int n = 0; n <= jtp.getText().length(); n++)
    115.	        {	 
    116.	        int length = jtp.getDocument().getLength(); 
    117.	        		 
    118.	try {
    119.	        			 
    120.	if(jtp.getDocument().getText(0, length).toString().charAt(n) == period)
    121.	{
    122.							
    123.	
    124.	 
    125.	jtp.paintComponent(g1);
    126.	if(i1 < 600)
    127.	i1++;
    128.	else
    129.	i1 = 100;
    130.					           
    131.					           
    132.				             
    133.	try 
    134.	{
    135.	jtp.getHighlighter().addHighlight(nz, n, highlightPainter);
    136.	} 
    137.	catch (BadLocationException e)
    138.	{
    139.	// TODO Auto-generated catch block
    140.	e.printStackTrace();
    141.	} 
    142.	nz = n + 1;
    143.	n++;
    144.	jtp.getHighlighter().removeAllHighlights();
    145.	length = jtp.getDocument().getLength();
    146.	String tempText = jtp.getDocument().getText(0, length).toString().substring(n,length);
    147.	jtp.setText(tempText);
    148.	n = 0; 
    149.	}
    150.	else
    151.	 {
    152.
    153.							
    154.	try 
    155.	{
    156.	jtp.getHighlighter().addHighlight(0, n, highlightPainter);
    157.	} 
    158.	catch (BadLocationException e)
    159.	{
    160.	// TODO Auto-generated catch block
    161.	e.printStackTrace();
    162.	} 
    163.						
    164.	}
    165.	} 
    166.	catch (BadLocationException e) {
    167.	// TODO Auto-generated catch block
    168.	e.printStackTrace();
    169.	}
    170.	}
    171.	}
    172.	}
    173.		
    174.	
    175.	}
    176.	private static class MyTextPane extends JTextPane 
    177.	{ 
    178.  public MyTextPane() 
    179.    { 
    180.        super(); 
    181.        setText("Hello World"); 
    182.        setOpaque(false); 
    183.        setBackground(new Color(0,0,0,0)); 
    184.    } 
    185.
    186.   @Override 
    187.    protected void paintComponent(Graphics g) 
    188.    { 
    189.    if(g1 == null)
    190.    {
    191.    g1 = g;
    192.    }
    193.    img = null; 
    194.    img = Toolkit.getDefaultToolkit().getImage("C:\\images\\" + i1 + ".jpg");            
    195.    g.drawImage(img, 0, 0, this); 
    196.   super.paintComponent(g); 
    197.    }
    198. }
    199. }

    How should I go about altering this code to allow java to release image/graphic/paintComponent cache from memory once a new image is painted?


  2. #2
    Administrator copeg's Avatar
    Join Date
    Oct 2009
    Location
    US
    Posts
    5,260
    Thanks
    176
    Thanked 818 Times in 761 Posts
    Blog Entries
    5

    Default Re: Properly releasing memory to avoid memory pileup/crash

    the memory usage goes up and the last image cache is never released from memory
    My recommendation: study the basics of java garbage collection - in short, worrying about memory is often futile. Objects aren't freed from memory immediately as the garbage collector will run when it needs to. If you truly feel there is a memory leak - for instance if an Exception is thrown because of it, which can happen if you hold onto references to object - then place your application through a profiler and study the object allocations. And please, when posting code, just post the code - those line numbers prevent anyone from trying to test your code (let alone try to read it)

  3. The Following User Says Thank You to copeg For This Useful Post:

    fickletrick (July 22nd, 2012)

  4. #3
    Super Moderator pbrockway2's Avatar
    Join Date
    Jan 2012
    Posts
    939
    Thanks
    6
    Thanked 202 Times in 178 Posts

    Default Re: Properly releasing memory to avoid memory pileup/crash

    I agree with copeg. Java was designed, in part, to free the programmer from having to perform various circus tricks like memory juggling or tightrope pointer arithmetic where one false step could spell disaster. Generally speaking the runtime will perform garbage collection, not the program as such. You only need worry if there is a problem (as demonstrated by the runtime performance for instance). And then you have to deal with what is an unusual circumstance by measuring and testing with a profiler.

    That said, garbage will only be collected if it *is* garbage.

    img = Toolkit.getDefaultToolkit().getImage("C:\\images\\" + i1 + ".jpg");

    The API docs for getImage() say, in part "The underlying toolkit attempts to resolve multiple requests with the same filename to the same returned Image. Since the mechanism required to facilitate this sharing of Image objects may continue to hold onto images that are no longer in use for an indefinite period of time, developers are encouraged to implement their own caching of images by using the createImage variant wherever available".

    Your code suggests there may be quite a number of these images (<500). If they are not intended to be reused the toolkit's caching mechanism would inappropriately hang on to unwanted data. If they are intended to be reused you should think about the advice that you implement your own caching strategy. (Elsewhere in the program you obtain images using ImageIO which also has a caching mechanism you should be aware of.)

    I'm not saying getImage() will cause a memory problem. For one thing the specific caching mechanism isn't specified and, for another, I doubt Oracle would be silly enough to use one that caused memory problems. But it probably will cause memory usage to grow long after an image has ceased to play any role in the program. And advice given in the API docs should be followed - at least, in my limited experience, its proven to be a good idea to do so.

    -----

    Concerning the code as a whole, the class should be named Storybook in line with Java coding conventions.

    You use static stuff in the code: variables (including the possibly problematic i2) and a class. I haven't read the code closely enough to see if this is wrong, so I'll stick with my prejudice that it very probably is wrong. main() must be static and mostly likely little else should be. Where exceptions exist (like static final "constants") you should have a clear idea why you are making them static: keeping the compiler quite when it alerts you to problems with a "static context", or "ease of access" from elsewhere in the code aren't sufficient reasons.

    The main() method is far too long. Consider using multiple classes each representing, in code, one specific type of thing. A "specific type of thing" in programming terms is expressible in terms of the statement: "It's something that can ...". In other words it is defined in terms of its behaviour.

    Oracle's Tutorial offers detailed examples and explanations about how to use the Swing gui API. Perhaps it would be worth consulting, and its patterns followed. Or others may be able to suggest resources that describe overall Swing usage without being quite as comprehensive as Oracle's Tutorial - because you often find yourself having to skip around a bit. In any case the use of a single "God class" which does everything isn't the right way to go.

    -----

    Sorry that my advice is more or less along the lines that you should step back from the program and look at overall class structure, Swing painting methods etc. But such it is: take it or leave it. Either way, good luck! It sounds like an interesting program.

  5. The Following User Says Thank You to pbrockway2 For This Useful Post:

    fickletrick (July 22nd, 2012)

  6. #4
    Junior Member
    Join Date
    Jul 2012
    Posts
    2
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Default Re: Properly releasing memory to avoid memory pileup/crash

    Thank you for the advice. I will familiarize myself with profiling and test the code after I first make some improvements. In regards to the basics of garbage collection in java I do recall that it is automated and should typically free memory without any leaks occurring. However I have done a really good job at thwarting its ability with the code that I put together here, going on an all nighter.

    When you say I should be breaking things down into subclasses, I get the feeling that this is the only real solution to the problem I'm having. With the current code, the application's memory usage explodes to 750mb before finally crashing... I was thinking I could test out my application idea by whipping up a quick big main with public variables, but clearly it is falling far short of being worth testing this way.

    From what I remember reading on garbage collection in java other than it being automated, is that items stored in cache are typically marked for garbage collection when they meet a certain criteria: an example was something along the lines of datatypes that are declared in a method are marked for garbage collection when the method completes and returns a value, the completion and return being proof that the encapsulated datatypes have finished their primary and only objective.

    Considering that I did not break down my code into subclasses and methods, I gave the environment little hope for collecting garbage intelligently, because the datatypes I declared never satisfy termination requirements from an enclosed type returning to a finished state.

    With that said, and hopefully correct enough, I am now going to divide the important sections of my main into appropriated methods, and I will post my code when I have found success, or perhaps any interesting scuffles along the way.

    Thanks again!

  7. #5
    Super Moderator jps's Avatar
    Join Date
    Jul 2012
    Posts
    2,642
    My Mood
    Daring
    Thanks
    90
    Thanked 263 Times in 232 Posts

    Default Re: Properly releasing memory to avoid memory pileup/crash

    Just a quick note: As was mentioned, java was designed to free you from worry of garbage collecion. As such, if you are not getting that old memory collected, then you have not released all pointers to it or something like that. This suggests a problem in your code no matter how you reformat what you have. You have to be sure to set all pointers pointing at the old image to point at a new image or null for that memory to be garbage.

  8. #6
    Member
    Join Date
    Jul 2012
    Posts
    119
    Thanks
    0
    Thanked 19 Times in 19 Posts

    Default Re: Properly releasing memory to avoid memory pileup/crash

    fickletrick,
    you declare 2 static objects....Static object affects the memory management behavior of JVM (auto Garbage Collector) because static object is an instance itself.

  9. #7
    Administrator copeg's Avatar
    Join Date
    Oct 2009
    Location
    US
    Posts
    5,260
    Thanks
    176
    Thanked 818 Times in 761 Posts
    Blog Entries
    5

    Default Re: Properly releasing memory to avoid memory pileup/crash

    One final point, which is a huge point that I overlooked given the improper formatting of your code but now have had time to look closer: there are many things wrong with how you are controlling your GUI. First, swing is single threaded. Meaning, do NOT try and call Swing methods from a different method (in this case the main method) unless you know what you are doing. Second, you are trying to call paintComponent, holding onto a reference to a Graphics object from the paintComponent method..this is a creative way to try and paint, but it is also incorrect. Third, you are loading an image from the paintComponent each time, this is not just inefficient but requires lots of system resources and references, and you do not know when paintComponent may be called. There are probably many more things that I won't get into.

    Start from the basics - learn how to draw Java2D the correct way.
    Trail: 2D Graphics (The Java™ Tutorials)

Similar Threads

  1. [SOLVED] Memory usage increasing in while loop - is it a memory leak
    By mds1256 in forum What's Wrong With My Code?
    Replies: 2
    Last Post: July 18th, 2012, 10:06 AM
  2. [SOLVED] Memory issues..?
    By Saintroi in forum What's Wrong With My Code?
    Replies: 10
    Last Post: April 24th, 2012, 10:31 PM
  3. In memory concept
    By VaniRathna in forum File I/O & Other I/O Streams
    Replies: 5
    Last Post: February 6th, 2012, 05:48 AM
  4. SwingWorker - max memory?
    By fractalorbit in forum AWT / Java Swing
    Replies: 1
    Last Post: September 15th, 2011, 02:58 PM
  5. Memory Handling -de allocate memory in Java
    By 19world in forum Java Theory & Questions
    Replies: 4
    Last Post: June 15th, 2010, 04:05 AM