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 4 of 4

Thread: JTable memory consumption

  1. #1
    Junior Member
    Join Date
    Nov 2010
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default JTable memory consumption

    Hello,
    I've implemented a simple JTable with a DefaultTableModel. For some reason, when scrolling back and forth over the data, memory consuption goes very high and eventually peaks without ever going back down. Is this normal behavior? System.gc() has been manually invoked but to no avail.

    Thanks ahead of time,
    ~Daniel


  2. #2
    Super Moderator helloworld922's Avatar
    Join Date
    Jun 2009
    Posts
    2,895
    Thanks
    23
    Thanked 619 Times in 561 Posts
    Blog Entries
    18

    Default Re: JTable memory consumption

    Could you post your code? It's possible you have something somewhere that's creating a lot of objects but aren't de-referencing them so the can be garbage collected.

  3. #3
    Junior Member
    Join Date
    Nov 2010
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: JTable memory consumption

    here is the table model class:

    package in.tune.gui.table;
     
    import in.tune.data.DataHandler;
     
    import javax.swing.table.AbstractTableModel;
     
    public class JBTableModel extends AbstractTableModel {
     
    	private static final long serialVersionUID = 1L;
     
    	private static int[] enabledColumns = {2, 0, 1, 3, 11, 12};
    	private static Column[] enabledColumns2 = {new Column(2), new Column(0), new Column(1), new Column(3), new Column(11), new Column(12)};
     
    	private static String[] columnNames = {"Album", "Artist", "Title", "Year", "Arranger", "Comment", "Disk", "Total Disks",
    		"Genre", "Language", "Rating", "Track", "Total Tracks"};
     
    	@Override
    	public String getColumnName(int col)
    	{
    		return columnNames[enabledColumns[col]];
    	}
     
    	public int getRowCount()
    	{
    		return DataHandler.getList().size();
    	}
     
    	public int getColumnCount()
    	{
    		return enabledColumns.length;
    	}
     
    	public Object getValueAt(int row, int col)
    	{
    		return enabledColumns2[col].getData(row);
    	}
     
    	@Override
    	public boolean isCellEditable(int row, int col)
    	{
    		return false;
    	}
     
    	@Override
    	public void setValueAt(Object value, int row, int col)
    	{
    		//note: never do anything here or in edit cells. The tag editor will be in a separate window. ~Daniel Centore
    	}
     
    }

    The DataHandler class:
    package in.tune.data;
     
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.Collections;
    import java.util.LinkedList;
    import java.util.List;
     
    /**
     * Handles the collection of all our songs
     * 
     * @author Daniel Centore
     *
     */
    public class DataHandler implements Serializable {
     
    	private static final String dataFile = "./songs.ser";
     
    	private static DataHandler instance = new DataHandler();
    	private List<Song> list = Collections.synchronizedList(new LinkedList<Song>());	//the main collection. Synchronized with Collections.
    	private List<String> data = Collections.synchronizedList(new LinkedList<String>());	//collection of data Strings. this will be used to reference to rather than storing every string
     
    	/**
    	 * Returns a reference to a clone of s if available, otherwise adds s to database and returns it
    	 * @param s - a string
    	 * @return - reference
    	 */
    	public static String getString(String s)
    	{
    		int i = Collections.binarySearch(instance.data, s);
    		if(i >= 0)
    		{
    			return instance.data.get(i);
    		}
    		else
    		{
    			instance.data.add(s);
    			Collections.sort(instance.data);
    			return s;
    		}
    	}
     
    	/**
    	 * Returns the main song list
    	 * @return
    	 */
    	public static List<Song> getList()
    	{
    		return instance.list;
    	}
     
    	public static void save()
    	{
    		FileOutputStream fos = null;
    		ObjectOutputStream out = null;
    		try {
    			fos = new FileOutputStream(dataFile);
    			out = new ObjectOutputStream(fos);
    			out.writeObject(instance);
    			out.close();
    		} catch(IOException ex) {
    			ex.printStackTrace();
    		}
    	}
     
    	public static void load()
    	{
    		FileInputStream fis = null;
    		ObjectInputStream in = null;
    		try
    		{
    			fis = new FileInputStream(dataFile);
    			in = new ObjectInputStream(fis);
    			instance = (DataHandler)in.readObject();	//possible dangerous?
    			in.close();
    		} catch(IOException ex) {
    			ex.printStackTrace();
    		} catch(ClassNotFoundException ex) {
    			ex.printStackTrace();
    		}
    	}
     
    }

    And finally the Song class:
    package in.tune.data;
     
    import java.io.File;
    import java.io.Serializable;
    import java.util.LinkedList;
     
    import org.jaudiotagger.audio.AudioFile;
    import org.jaudiotagger.audio.AudioFileIO;
    import org.jaudiotagger.audio.AudioHeader;
     
    /**
     * Class representing a song
     * 
     * @author Daniel Centore
     *
     */
    public class Song implements Serializable {
     
    	private static final long serialVersionUID = 1L;
     
    	boolean isSong = false;		//set to true if it is
     
    	LinkedList<String> tags = new LinkedList<String>();		//list of tags. Folllows order in ReadTags
    	File location = null;
     
    	/**
    	 * Returns the length of the song in seconds
    	 * @return -1 if audio file could not be read
    	 */
    	public int getTrackLength()
    	{
    		AudioFile af;
    		try {
    			af = AudioFileIO.read(location);
    			AudioHeader i = af.getAudioHeader();
     
    			return i.getTrackLength();
    		} catch (Exception e) {
    			System.err.println("Error: audio file not found? Stack trace: ");
    			e.printStackTrace();
    		}
     
    		return -1;
    	}
     
    	/**
    	 * Inits a song at the location f
    	 * @param f
    	 */
    	public Song(File f)
    	{
    		location = f;
    		isSong = ReadTags.updateTags(tags, location);
    	}
     
    	/**
    	 * Inits a Song at the String s (file path)
    	 * TODO: add samba share support (via library or auto mounting?)
    	 * @param s
    	 */
    	public Song(String s)
    	{
    		this(new File(s));
    	}
     
    	@Override
    	public String toString()
    	{
    		return "Song [tags=" + tags + "]";
    	}
     
    	/**
    	 * Returns the tags
    	 * @return
    	 */
    	public LinkedList<String> getTags()
    	{
    		return tags;
    	}
     
    }

    Edit: sorry forgot about this last class you may need:
    package in.tune.gui.table;
     
    import in.tune.data.DataHandler;
     
    import java.util.GregorianCalendar;
     
    /**
     * Class representing a single column of the data table
     * 
     * @author Daniel Centore
     *
     */
    public class Column {
     
    	private int col;	//the column its representing
     
    	/**
    	 * inits a column at column col
    	 * 
    	 * @param _col
    	 */
    	public Column(int _col)
    	{
    		col = _col;
    	}
     
    	/**
    	 * returns a String of data in the column
    	 * @param row - the row its in. Row 0 is the 1st row of DATA (not titles)
    	 * @return - the data
    	 */
    	public String getData(int row)
    	{
    		switch(col)
    		{
    		case -1:
    			return formatSecs(DataHandler.getList().get(row).getTrackLength());
     
    		default:
    			return DataHandler.getList().get(row).getTags().get(col);
    		}
    	}
     
    	/**
    	 * Returns a
    	 * @param secsIn
    	 * @return
    	 */
    	public static String formatSecs(int secs)		//TODO: finish this
    	{
    		GregorianCalendar g = new GregorianCalendar();
    		g.setTimeInMillis(secs * 1000);
     
    		int hours = g.get(GregorianCalendar.HOUR_OF_DAY);
    		int mins = g.get(GregorianCalendar.MINUTE);
    		int seconds = g.get(GregorianCalendar.SECOND);
     
    		return hours+"";
    	}
     
    }
    Last edited by drdanielfc; November 27th, 2010 at 02:52 PM. Reason: forgot

  4. #4
    Junior Member
    Join Date
    Nov 2010
    Posts
    5
    Thanks
    0
    Thanked 2 Times in 2 Posts

    Default Re: JTable memory consumption

    I found a couple of suspicious things. The first most suspicious was this:
    	public int getTrackLength()
    	{
    		AudioFile af;
    		try {
    			af = AudioFileIO.read(location);
    			AudioHeader i = af.getAudioHeader();
     
    			return i.getTrackLength();
    		} catch (Exception e) {
    			System.err.println("Error: audio file not found? Stack trace: ");
    			e.printStackTrace();
    		}
     
    		return -1;
    	}

    If this thing is doing a ton of file I/O every time you want to show a track length, that could be a problem. I am not sure how often that gets called, but I would comment it out and replace it with a constant integer and see what happens.

    Another interesting bit was this:
    	public static String getString(String s)
    	{
    		int i = Collections.binarySearch(instance.data, s);
    		if(i >= 0)
    		{
    			return instance.data.get(i);
    		}
    		else
    		{
    			instance.data.add(s);
    			Collections.sort(instance.data);
    			return s;
    		}
    	}


    I see that it adds something of it doesn't find it.

    No idea if either of these is your problem, I just took a quick glance. I would trim down to the most basic implementation possible, step by step, and see if the problem goes away or not.

Similar Threads

  1. Memory Handling -de allocate memory in Java
    By 19world in forum Java Theory & Questions
    Replies: 4
    Last Post: June 15th, 2010, 04:05 AM
  2. Out of Memory Error
    By wasaki in forum What's Wrong With My Code?
    Replies: 1
    Last Post: May 31st, 2010, 03:37 PM
  3. free memory of bufferedimage
    By mr_empty in forum Java SE APIs
    Replies: 2
    Last Post: January 19th, 2010, 06:14 AM
  4. Java memory management
    By trueacumen in forum Java Theory & Questions
    Replies: 5
    Last Post: August 12th, 2009, 02:40 AM
  5. Replies: 10
    Last Post: June 22nd, 2009, 07:45 AM

Tags for this Thread