0

I have been reading some stuffs on how the garbage collector works in Java, but I'm not sure to correctly understand what it is doing in reality. So I've been creating an ugly program...

The only thing it does is:

  • You hit the Add button and you create a TreeMap of 80K elements that is added to a vector
  • You hit the Remove button, and you remove the last element in the vector

        public class modelTester {
            public static Date getToday(){
                Calendar cal = Calendar.getInstance();
                return getDate(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH),0,0);
            }
    
            public static Date getDate(Integer year, Integer month, Integer day, Integer hour, Integer minute){
                Calendar calendar = Calendar.getInstance();
                calendar.set(Calendar.YEAR, year);
                calendar.set(Calendar.MONTH, month);
                calendar.set(Calendar.DAY_OF_MONTH, day);
                calendar.set(Calendar.HOUR_OF_DAY, hour);
                calendar.set(Calendar.MINUTE, minute);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);
    
                return calendar.getTime();
            }
    
            public static void main(String[] args) {    
                JFrame frame = new JFrame();
                frame.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        System.exit(0); 
                    }
                });
    
                final Vector<TreeMap<Date, Double>> v = new Vector<TreeMap<Date, Double>>();
    
                JPanel panel = new JPanel(new FlowLayout());
                JButton addButton = new JButton("add data");
                JButton removeButton = new JButton("remove data");
                JButton runGCButton = new JButton("run Garbage Collector");
    
    
                panel.add(addButton);
                panel.add(removeButton);
                panel.add(runGCButton);
    
                frame.getContentPane().add(panel);
    
    
                addButton.addActionListener(new ActionListener() {
    
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        TreeMap<Date, Double> data = new TreeMap<Date, Double>();
                        for (int i =0; i < 80000; i++){
                            data.put(new Date(getToday().getTime() - i), new Double(i));
                        }
    
                        v.add(data);
                        System.out.println("Adding Data => Vector Size = " + v.size());
                    }
                });
    
    
                removeButton.addActionListener(new ActionListener() {
    
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if(v.size() !=0){
                            v.remove(v.size()-1);
                        }   
                        System.out.println("Removing Data => Vector Size = " + v.size());
                    }
                });
    
                runGCButton.addActionListener(new ActionListener() {
    
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("Yeah, collecting garbage");
                        System.gc();
                    }
                });
    
                frame.setSize(150,150);
                frame.setVisible(true);
    
            }
        }
    

After adding a few data and then removing everything, I am ending up with this memory consumption.

enter image description here

How come the program still use that amount of memory given that I don't have anymore references on the maps when removing them from the vector ?

Thanks for your help

EDIT AFTER USING VISUAL VM

enter image description here

BlackLabrador
  • 2,829
  • 5
  • 18
  • 21
  • Are you *sure* that the gc even ran? – awksp Jun 20 '14 at 04:25
  • I don't know actually... 45 minutes later, the program still uses the same memory... – BlackLabrador Jun 20 '14 at 04:29
  • I wouldn't be surprised if it's just that the GC hasn't run. It usually doesn't run unless there's pressure to free more memory, to generalize how it behaves. Because you aren't doing anything, I wouldn't be surprised to see that the GC didn't do anything. What happens if you try to put in some calls to `System.gc()`? It's only a suggestion to gc, but it usually seems to work... – awksp Jun 20 '14 at 04:31
  • Well, after adding a third button to force the System to garbage collect, it does not have much effect – BlackLabrador Jun 20 '14 at 04:49
  • Hm. Perhaps grab a profiler and see what exactly is making up the heap? – awksp Jun 20 '14 at 04:51
  • How do you do that ? Am using eclipse, is there a way to monitor this ? – BlackLabrador Jun 20 '14 at 04:54
  • 1
    Check out [VisualVM](http://visualvm.java.net/) – awksp Jun 20 '14 at 04:57
  • @BlackLabrador I think is that you are getting the data in a static way – Rod_Algonquin Jun 20 '14 at 04:58
  • @user3580294, Thanks, am going to download this. – BlackLabrador Jun 20 '14 at 05:06
  • No problem. Let me know what you learn! – awksp Jun 20 '14 at 05:07
  • @Rod_Algonquin I'm not sure I understand what you're saying. what do you mean in a static way ? But since I removing references to the TreeMap in the vector, it should be garbage collected at one point, no ? – BlackLabrador Jun 20 '14 at 05:08
  • The task manager won't show anything reliable since the operating system will not reclaim, and the process won't return, memory. This doesn't cause a problem, since pages not in use aren't occupying physical memory. - That's not a good way to learn more about GC! – laune Jun 20 '14 at 06:02

1 Answers1

1

As laune has said, the memory won't be reclaimed by the operating system. The JVM reserves a minimum amount of memory for the heap at startup (configured with the Xms setting) and grows it as necessary up to the maximum (the Xmx setting). It will never release memory back to the operating system.

To see how much of the heap space is actually being used, there are various tools available. VisualVM is one of the best free ones, it will show you the heap space usage, and will even give you a live histogram showing the amount of memory used by objects of each class.

Dave Morrissey
  • 4,371
  • 1
  • 23
  • 31
  • Thanks for the answer. After reviewing it with visual VM, it seems that this is actually what's happening. The used heap is nill but the heap size is huge... Why won't the JVM realease some memory back to the system. What's the idea behind that ? – BlackLabrador Jun 20 '14 at 06:44
  • 1
    @BlackLabrador Usually an application runs and its memory requirement grow and then stay the same (or drop just to grow later again). Your application is a rare exception and I guess nobody cares about such a case. Or there may be some technical difficulty... maybe a good idea for another question. But I've found [this](http://stackoverflow.com/questions/675589) and [this](http://stackoverflow.com/questions/324499) already. – maaartinus Jun 20 '14 at 07:24