Page 1 of 2 12 LastLast
Results 1 to 20 of 21

Thread: Memory usage

  1. #1
    Moon_E is offline Member
    Join Date
    Jul 2010
    Posts
    8
    Rep Power
    0

    Default Memory usage

    Hi, this is my first post here.

    I stumbled upon this issue some time ago and I never found out if it has to do something with my code or if it is normal.

    So, my program uses a large amount of memory but after it has finished the memory used is not freed for other processes.

    Here is an example program for explanation
    It is supposed to store the array in the "History" class and then add it to an ArrayList for later usage but each History item may be deleted if needed.
    When adding, memory usage in Windows Task Manager goes up, but when it is deleted it doesn't decrease. (Though it is possible to add new History items without memory increase.)
    Java Code:
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    
    
    public class MyTestClass extends JFrame {
    	
    	public MyTestClass() {
    		MyPanel p = new MyPanel();
    		setContentPane(p);
    	}
    	
    	public static void main(String[] args) {
    		JFrame MyTestClass = new MyTestClass();
    		MyTestClass.setDefaultCloseOperation(EXIT_ON_CLOSE);
    		MyTestClass.pack();
    		MyTestClass.setVisible(true);
    	}
    }
    
    class History {
    	public final int[][] bigArray;
    	
    	public History (int[][] bigArray) {
    		this.bigArray = bigArray;
    	}
    }
    
    class MyPanel extends JPanel {
    	JButton BtAdd = new JButton("Add");
    	JButton BtDelete = new JButton("Delete");
    	JLabel LbHistorySize = new JLabel("Size 0");
    	ArrayList<History> history = new ArrayList<History>();
    	
    	public MyPanel() {
    		BtAdd.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				history.add(new History(new int[4000][4000]));
    				LbHistorySize.setText("Size" + history.size());
    			}
    		});
    		BtDelete.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				history.remove(0);
    				LbHistorySize.setText("Size " + history.size());
    			}
    		});
    		add(BtAdd);
    		add(BtDelete);
    		add(LbHistorySize);
    	}
    }

  2. #2
    Norm's Avatar
    Norm is online now Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,401
    Rep Power
    25

    Default

    I think the the JVM will continue to acquire memory if it needs it but may not free it when its not being used.
    Have to look at the specifications or implementation docs

  3. #3
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    Yep. It depends on the JVM, but generally it will grab memory up to xMx as needed, and will be slow to release it. After all, if it needed that memory once, and since you said that's the memory that's available to it (that's what xMx is), why give it back?

  4. #4
    j2me64's Avatar
    j2me64 is offline Senior Member
    Join Date
    Sep 2009
    Location
    Zurich, Switzerland
    Posts
    962
    Rep Power
    6

    Default

    Quote Originally Posted by Moon_E View Post
    When adding, memory usage in Windows Task Manager goes up, but when it is deleted it doesn't decrease.

    in java memory is allocated only to objects, like your object called history. in order that an object becomes eligible for the garbage collector its reference must point to null. but in java even if you call the gc explicitly there is no garantee when the gc will run. what you can try is set your object reference to null and then make a call to the gc().

  5. #5
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    Do not call gc() directly. There is (almost) never a need for that.
    Similarly setting references to null is (almost) never needed.

    Finally the memory the JVM uses in the system is not the same as the amount used in the heap. The JVM grabs memory as needed up to xMx and only rarely releases it.

  6. #6
    j2me64's Avatar
    j2me64 is offline Senior Member
    Join Date
    Sep 2009
    Location
    Zurich, Switzerland
    Posts
    962
    Rep Power
    6

    Default

    Quote Originally Posted by Tolls View Post
    Finally the memory the JVM uses in the system is not the same as the amount used in the heap. The JVM grabs memory as needed up to xMx and only rarely releases it.

    this is not true. try the code in this Using totalMemory( ) and freeMemory( ) in Java

  7. #7
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    I have, and the amount available for the heap is not the same as the amount used.

    The OP is asking why the memory shown by the Task Manager is not going down, and the reason is that, though the gc may have reclaimed the memory from the object that does not mean the JVM has handed it back to the system. These are two different mechanisms.

    All that the gc did, in this case, is increase the amount of heap available...it did not hand any memory back to the system.

  8. #8
    j2me64's Avatar
    j2me64 is offline Senior Member
    Join Date
    Sep 2009
    Location
    Zurich, Switzerland
    Posts
    962
    Rep Power
    6

    Default

    Quote Originally Posted by Tolls View Post
    The OP is asking why the memory shown by the Task Manager is not going down

    because the object is not eligible for the gc.

  9. #9
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    I don't think you understand how the memory assigned to the JVM works.

    When the gc releases an object and frees up the memory associated with that object that memory simply becomes available to the heap...not to the system. The JVM does not hand that memory back to the system.

  10. #10
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,519
    Blog Entries
    7
    Rep Power
    20

    Default

    The virtual machine can only hand over memory back to the system when it has freed a bunch of objects near the end of the virtual process space; the memory has to be one contiguous area. Read the man pages for brk and sbrk and you'll see.

    kind regards,

    Jos

  11. #11
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    Quite, and even then it doesn't have to hand it back. I'm not sure what rules it uses, but I assume it's JVM dependent.

  12. #12
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,519
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by Tolls View Post
    Quite, and even then it doesn't have to hand it back. I'm not sure what rules it uses, but I assume it's JVM dependent.
    I played with it once: Sun's JVM compacts its 'new' space (where short-lived objects exist) but doesn't relinguish optional memory then; i.e. it only does/did that after a full garbage collection (where also 'eden space', where the old objects live) is compacted again. I don't really care, it's only virtual memory and no other process has access to it in my case and it doesn't hinder other processes either; only when -Xmx was chosen too large it might hit the virtual memory image swap file(s) ...

    kind regards,

    Jos

  13. #13
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    And once you hit swap space then you hit a completely different problem...one that is based purely around your code using too much memory.
    :)

  14. #14
    Moon_E is offline Member
    Join Date
    Jul 2010
    Posts
    8
    Rep Power
    0

    Default

    Thank you for your answers

    @Tolls: What is the disadvantage of calling gc()?

    Those two swithes for the JVM are supposed to handle physical memory usage, but they don't work as i'd expect them to.
    Java Code:
     -XX:MaxHeapFreeRatio=50
     -XX:MinHeapFreeRatio=30
    As i understand it this controls the physical memory used after full gc. It should release memory to the system, if free memory is 50% of total memory. And likewise if free memory is less than 30% of total memory it should allocate more until it is 30%.

    But thats not how it worked when I tested it with the code below.
    I added a button for manual garbage collection, and memory used does decrease, though only after hitting it 3+ times mostly, which may be due to the GC not compacting old memory it still uses, as JosAH pointed out.

    Java Code:
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    
    
    public class MyTestClass extends JFrame {
    	
    	public MyTestClass() {
    		MyPanel p = new MyPanel();
    		setContentPane(p);
    	}
    	
    	public static void main(String[] args) {
    		JFrame MyTestClass = new MyTestClass();
    		MyTestClass.setDefaultCloseOperation(EXIT_ON_CLOSE);
    		MyTestClass.pack();
    		MyTestClass.setVisible(true);
    	}
    }
    
    class History {
    	public final int[][] bigArray;
    	
    	public History (int[][] bigArray) {
    		this.bigArray = bigArray;
    	}
    }
    
    class MyPanel extends JPanel {
    	Runtime runtime;
    	JButton BtAdd = new JButton("Add");
    	JButton BtDelete = new JButton("Delete");
    	JButton BtGC = new JButton("GC");
    	JLabel LbHistorySize = new JLabel("Size 0 ");
    	ArrayList<History> history = new ArrayList<History>();
    	
    	public MyPanel() {
    		//Getting the runtime reference from system
    		runtime = Runtime.getRuntime();
    		BtAdd.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				history.add(new History(new int[4000][4000]));
    				LbHistorySize.setText("Size" + history.size());
    			}
    		});
    		BtDelete.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				history.remove(history.size()-1);
    				LbHistorySize.setText("Size " + history.size());
    			}
    		});
    		BtGC.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				System.out.println("##### Heap utilization statistics #####");
    				printMemUsage("before");
    				runtime.gc();
    				printMemUsage("after");
    			}
    		});
    		add(BtAdd);
    		add(BtDelete);
    		add(BtGC);
    		add(LbHistorySize);
    	}
    	
    	public void printMemUsage(String time) {
    		int mb = 1024*1024;
    		System.out.println("## " + time + " ##");
    		//Print used memory
    		System.out.println("Used Memory:" + (runtime.totalMemory() - runtime.freeMemory()) / mb + " MB");
    		//Print free memory
    		System.out.println("Free Memory:" + runtime.freeMemory() / mb + " MB");
    		//Print total available memory
    		System.out.println("Total Memory:" + runtime.totalMemory() / mb + " MB");
    		//Print Maximum available memory
    		System.out.println("Max Memory:" + runtime.maxMemory() / mb + " MB");
    	}
    }
    Little clarification why this bothers me:
    The program i wrote/write, and which i want to free some memory from time to time, stores several images in RAM, which may be deleted if the user doesn't want to keep them, and when they are deleted there is perhaps quite some memory used unnecessarily.

  15. #15
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    In almost all situations gc() is a sign that you've written something wrong. It does not solve an OutOfMemory, since a full gc() is automatically called when you try and create a new object and the heap is full, and before that exception is thrown.

    That memory used will be reclaimed eventually. Are you wanting to hand it back to the system?

    And this:
    Java Code:
    				runtime.gc();
    				printMemUsage("after");
    does not guarantee a gc run before that print is done. It's merely a suggestion to the JVM to run it, and it'll do it when it feels like it.

  16. #16
    Moon_E is offline Member
    Join Date
    Jul 2010
    Posts
    8
    Rep Power
    0

    Default

    yes, i do want to hand back the memory to the system. I don't get OutOfMemoryError.
    Calling gc() once doesn't hand back any memory, as far as i tested. It needs to be run several times until memory is released.

    does not guarantee a gc run before that print is done. It's merely a suggestion to the JVM to run it, and it'll do it when it feels like it.
    when i tested it, calling gc() worked fine. (i ran with -verbose:gc)
    Last edited by Moon_E; 07-08-2010 at 09:56 PM.

  17. #17
    senorbum is offline Member
    Join Date
    Aug 2009
    Posts
    76
    Rep Power
    0

    Default

    Quote Originally Posted by Moon_E View Post
    yes, i do want to hand back the memory to the system. I don't get OutOfMemoryError.
    Calling gc() once doesn't hand back any memory, as far as i tested. It needs to be run several times until memory is released.


    when i tested it, calling gc() worked fine. (i ran with -verbose:gc)
    When you set the max memory the system can use, it always assumes that it can use that much, so it has no timetable to return it to system usage. Calling gc() has nothing to do with returning memory to the system. Garbage collecting relates to returning memory to the heap. The available memory at some point may return back to the system, but to my knowledge there is no guarantee that this will happen. You are telling your program that it can have a set amount of memory if it wants it. If you don't want to give it that memory, don't set it that high.

  18. #18
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    Quote Originally Posted by Moon_E View Post
    when i tested it, calling gc() worked fine. (i ran with -verbose:gc)
    It will garbage collect but there is nothing to say when. It is, and the documentation says this, a request. When that request is fulfilled is up to the JVM.

    Do not rely on gc().

  19. #19
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,519
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by Moon_E View Post
    yes, i do want to hand back the memory to the system.
    But why? No matter how much memory your process uses (unless it hit the swap space) it doesn't hinder other processes, that's how virtual memory works. Leave all memory management to the jvm and its garbage collector and all will be fine.

    kind regards,

    Jos

  20. #20
    Moon_E is offline Member
    Join Date
    Jul 2010
    Posts
    8
    Rep Power
    0

    Default

    If I load a large image into any non-java program it's going to use as much memory as needed, and if i eventually save it to disk or delete it, all memory associated with that image will be released.
    Java is different.
    It might release it, or not. And I thought I'd be able to do it as with other programs.

Page 1 of 2 12 LastLast

Similar Threads

  1. heap memory usage anomaly?
    By jon80 in forum Threads and Synchronization
    Replies: 1
    Last Post: 06-30-2009, 06:56 AM
  2. Replies: 2
    Last Post: 12-07-2008, 06:13 PM
  3. Replies: 2
    Last Post: 08-21-2008, 07:33 PM
  4. JVM memory usage
    By lardum in forum New To Java
    Replies: 7
    Last Post: 06-26-2008, 03:30 AM
  5. Latest XML parsing and memory usage benchmark
    By Jimmy Zhang in forum XML
    Replies: 0
    Last Post: 03-03-2008, 09:49 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •