Skip to main content

[memorypoolview~source-code-repository:87d7355d] Updated copyright

  • From:
  • To:
  • Subject: [memorypoolview~source-code-repository:87d7355d] Updated copyright
  • Date: Mon, 25 Mar 2013 13:07:40 +0000

Project:    memorypoolview
Repository: source-code-repository
Revision:   87d7355d5c9e5777a959370902c8eb9eff23d773
Author:     pingtimeout
Date:       2013-03-18 16:28:42 UTC
Link:       

Log Message:
------------
Added first implementation of garbage collectors support.
Moved perm gen data in the same box as old gen
Added last GC duration
Added last GC duration for IBM J9 and Hotspot
Garbage collector panels are now sorted so that young generation GC are
displayed first, regardless of their names.
Added garbage collector summary panel
Removed duplicated data (gc name in model)
Added Hotspot garbage collectors
Renamed Collections to Collection
Fixed GC detection, now when an unknown GC is detected, no NPE is thrown
Removed Constants class
Replaced "Generation" by the order in which GC will be displayed.
The "Generation" enum was added only to have Young GC being displayed
before old/full GC. This information is misleading since the only thing
needed here is an order.
The implementation of Comparator on GCModel now follows the contract of
the Comparactor interface.
GC Charts are now updated at every JMX flush notification
Removed GarbageCollection summary panel
Updated copyright


Revisions:
----------
8010815c37800f9b97c16c1fbfd4c140912f166c
c4919aeb5bd08828dad1f176c9ca1090542b1ca4
a80d37bce0cf69dc66de734c06561147ec0e1495
584a0259a291d176ed40df8c7f00b791eaa96b4f
b1b5335e8bc4573b1f1d9886eeb78125a4629f2d
243fd8b0ad8e4791869d2349dcb7bb22dcd85027
68c0faf3c9ec4a8fdc23566934d69910a0e0f3dd
dcf789ba6468b7d77ea5454c4d456654b351dd5b
6b7274c3c1f3050309855d4f2ee5ee21de33714e
68447e4ef452a352cd45ddbc075dff8f0b373c34
b5abb03263f30ec5fed2d69b0c7e2d0a3b3ffb3c
249b26877928dda063145e20f240e53b0f236857
f71e4844ebb900b664b9bb2e1726fbb54541f76c
87d7355d5c9e5777a959370902c8eb9eff23d773


Modified Paths:
---------------
src/com/kodewerk/visualvm/memorypools/MemoryPoolPanel.java
src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
src/com/kodewerk/visualvm/memorypools/PanelPositions.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
src/com/kodewerk/visualvm/memorypools/gc/Collections.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorSummaryPanel.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollector.java
src/com/kodewerk/visualvm/memorypools/gc/Collection.java
build.xml
src/com/kodewerk/visualvm/memorypools/Bundle.properties
src/com/kodewerk/visualvm/memorypools/Installer.java
src/com/kodewerk/visualvm/memorypools/MemoryPoolModel.java
src/com/kodewerk/visualvm/memorypools/MemoryPoolModelListener.java
src/com/kodewerk/visualvm/memorypools/MemoryPoolViewProvider.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModelListener.java
src/com/kodewerk/visualvm/memorypools/layer.xml


Added Paths:
------------
src/com/kodewerk/visualvm/memorypools/Constants.java
src/com/kodewerk/visualvm/memorypools/PanelPositions.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModelListener.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
src/com/kodewerk/visualvm/memorypools/gc/Collections.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollector.java
src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorSummaryPanel.java
src/com/kodewerk/visualvm/memorypools/gc/Generation.java
src/com/kodewerk/visualvm/memorypools/gc/Collection.java


Diffs:
------
diff --git a/src/com/kodewerk/visualvm/memorypools/Constants.java 
b/src/com/kodewerk/visualvm/memorypools/Constants.java
new file mode 100644
index 0000000..8b9fec8
--- /dev/null
+++ b/src/com/kodewerk/visualvm/memorypools/Constants.java
@@ -0,0 +1,28 @@
+package com.kodewerk.visualvm.memorypools;
+
+import javax.management.ObjectName;
+
+public class Constants {
+    public final static ObjectName GARBAGE_COLLECTOR_WILDCARD_PATTERN = 
createGarbageCollectorWilcardPattern();
+    public volatile static ObjectName MEMORY_POOL_WILDCARD_PATTERN = 
createMemoryPoolWilcardPattern();
+
+    public final static long ONE_MEGABYTE_SIZE = 1048576;
+
+    public static final String IMAGE_PATH = 
"com/kodewerk/visualvm/memorypools/resources/monitor.png";
+
+    private static ObjectName createGarbageCollectorWilcardPattern() {
+        try {
+            return new ObjectName("java.lang:type=GarbageCollector,name=*");
+        } catch (Exception ignored) {
+            return null;
+        }
+    }
+
+    private static ObjectName createMemoryPoolWilcardPattern() {
+        try {
+            return new ObjectName("java.lang:type=MemoryPool,name=*");
+        } catch (Exception ignored) {
+            return null;
+        }
+    }
+}
diff --git a/src/com/kodewerk/visualvm/memorypools/MemoryPoolPanel.java 
b/src/com/kodewerk/visualvm/memorypools/MemoryPoolPanel.java
index 8c8e041..ad9e69b 100644
--- a/src/com/kodewerk/visualvm/memorypools/MemoryPoolPanel.java
+++ b/src/com/kodewerk/visualvm/memorypools/MemoryPoolPanel.java
@@ -27,18 +27,16 @@ import javax.swing.JPanel;
  * @author kirk
  */
 public class MemoryPoolPanel extends JPanel implements 
MemoryPoolModelListener {
-
-    private final static long ONE_MEGABYTE = 1048576;
     private SimpleXYChartSupport chart;
 
     public MemoryPoolPanel(String name) {
         setLayout(new BorderLayout());
-        SimpleXYChartDescriptor description = 
SimpleXYChartDescriptor.bytes(ONE_MEGABYTE, false, 1000);
+        SimpleXYChartDescriptor description = 
SimpleXYChartDescriptor.bytes(Constants.ONE_MEGABYTE_SIZE, false, 1000);
         description.setDetailsItems(new String[3]);
 
         description.addLineItems("Memory Pool Size");
         description.addLineItems("Memory Pool Used");
-        description.setDetailsItems(new String[]{"Size", "Used","Max"});
+        description.setDetailsItems(new String[]{"Size", "Used", "Max"});
 
         chart = ChartFactory.createSimpleXYChart(description);
         add(chart.getChart(),BorderLayout.CENTER);
diff --git a/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java 
b/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
index 68bfcbe..d45fd02 100644
--- a/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
+++ b/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
@@ -17,53 +17,35 @@
 
 package com.kodewerk.visualvm.memorypools;
 
+import com.kodewerk.visualvm.memorypools.gc.GarbageCollectorModel;
+import com.kodewerk.visualvm.memorypools.gc.GarbageCollectorPanel;
 import com.sun.tools.visualvm.application.Application;
 import com.sun.tools.visualvm.core.ui.DataSourceView;
 import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
 import com.sun.tools.visualvm.tools.jmx.JmxModel;
 import com.sun.tools.visualvm.tools.jmx.JmxModelFactory;
-import java.awt.Point;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import javax.management.AttributeNotFoundException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanServerConnection;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
-import javax.swing.BorderFactory;
-import javax.swing.ImageIcon;
-import javax.swing.JEditorPane;
 import org.openide.util.Exceptions;
 import org.openide.util.ImageUtilities;
 
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.swing.*;
+import java.awt.*;
+import java.io.IOException;
+import java.util.ArrayList;
+
 /**
- *
  * @author kirk
  */
 class MemoryPoolView extends DataSourceView {
-    
-    private volatile static ObjectName MEMORY_POOL_WILDCARD_PATTERN =  null;
-    private final static HashMap<String,Point> positions;
-    private static final String IMAGE_PATH = 
"com/kodewerk/visualvm/memorypools/resources/monitor.png";
-    private ArrayList<MemoryPoolModel> models = new 
ArrayList<MemoryPoolModel>();
+    private ArrayList<MemoryPoolModel> memoryPoolModels = new 
ArrayList<MemoryPoolModel>();
+    private ArrayList<GarbageCollectorModel> garbageCollectorModels = new 
ArrayList<GarbageCollectorModel>();
     private DataViewComponent dvc;
-    
-    public static ObjectName getMemoryPoolWildcardPattern() {
-        //Exception can't happen as this is a constant.
-        //And, who cares if it gets overwritten. This should be final but...
-        if ( MEMORY_POOL_WILDCARD_PATTERN == null)
-            try {
-                MEMORY_POOL_WILDCARD_PATTERN = new 
ObjectName("java.lang:type=MemoryPool,name=*");
-            } catch (Throwable t) {}
-        return MEMORY_POOL_WILDCARD_PATTERN;
-    }
 
     public MemoryPoolView(Application application) {
-        super(application,"Memory Pools", new 
ImageIcon(ImageUtilities.loadImage(IMAGE_PATH, true)).getImage(), 60, false);
+        super(application, "Memory Pools", new 
ImageIcon(ImageUtilities.loadImage(Constants.IMAGE_PATH, true)).getImage(), 
60, false);
     }
-    
+
     public static MBeanServerConnection getMBeanServerConnection(Application 
application) {
         JmxModel jmx = JmxModelFactory.getJmxModelFor(application);
         return jmx == null ? null : jmx.getMBeanServerConnection();
@@ -80,103 +62,88 @@ class MemoryPoolView extends DataSourceView {
         DataViewComponent.MasterView masterView = new 
DataViewComponent.MasterView("Memory Pools", "View of Memory Pools", 
generalDataArea);
 
         //Configuration of master view:
-        DataViewComponent.MasterViewConfiguration masterConfiguration =
-                new DataViewComponent.MasterViewConfiguration(false);
+        DataViewComponent.MasterViewConfiguration masterConfiguration = new 
DataViewComponent.MasterViewConfiguration(false);
 
         //Add the master view and configuration view to the component:
         dvc = new DataViewComponent(masterView, masterConfiguration);
-        findMemoryPools();
 
-        MemoryPoolPanel panel;
-        for ( MemoryPoolModel model : models) {
-            panel = new MemoryPoolPanel(model.getName());
-            model.registerView(panel);
-            Point position = calculatePosition(model.getName());
-            dvc.addDetailsView(new DataViewComponent.DetailsView(
-                model.getName(), "memory pool metrics", position.y, panel, 
null), position.x);
-        }
+        findMemoryPoolsAndCreatePanels();
+        findGarbageCollectorsAndCreatePanels();
 
         return dvc;
     }
 
-    protected void findMemoryPools() {
+    private void findMemoryPoolsAndCreatePanels() {
+        findMemoryPools();
+        PanelPositions positions = new PanelPositions();
+        for (MemoryPoolModel model : memoryPoolModels) {
+            createMemoryPoolPanelFor(model, positions);
+        }
+    }
+
+    private void findMemoryPools() {
         try {
-            MBeanServerConnection conn = getMBeanServerConnection( 
(Application)super.getDataSource());
-            for (ObjectName name : 
conn.queryNames(getMemoryPoolWildcardPattern(), null)) {
-                initializeModel(name, conn);
+            MBeanServerConnection conn = 
getMBeanServerConnection((Application) super.getDataSource());
+            for (ObjectName name : 
conn.queryNames(Constants.MEMORY_POOL_WILDCARD_PATTERN, null)) {
+                initializeMemoryPoolModel(name, conn);
             }
         } catch (IOException e) {
             Exceptions.printStackTrace(e);
         }
     }
 
-    protected void initializeModel(ObjectName mbeanName, 
MBeanServerConnection conn) {
+    private void createMemoryPoolPanelFor(MemoryPoolModel model, 
PanelPositions positions) {
+        MemoryPoolPanel panel = new MemoryPoolPanel(model.getName());
+        model.registerView(panel);
+        Point position = positions.of(model.getName());
+        DataViewComponent.DetailsView detailsView = new 
DataViewComponent.DetailsView(
+                model.getName(), "memory pool metrics", position.y, panel, 
null);
+        dvc.addDetailsView(detailsView, position.x);
+    }
+
+    private void initializeMemoryPoolModel(ObjectName mbeanName, 
MBeanServerConnection conn) {
         try {
-            MemoryPoolModel model = new 
MemoryPoolModel(mbeanName,JmxModelFactory.getJmxModelFor((Application)super.getDataSource()),
 conn);
-            models.add(model);
-        } catch (MBeanException e) {
-            Exceptions.printStackTrace(e);
-        } catch (AttributeNotFoundException e) {
-            Exceptions.printStackTrace(e);
-        } catch (InstanceNotFoundException e) {
-            Exceptions.printStackTrace(e);
-        } catch (ReflectionException e) {
+            MemoryPoolModel model = new MemoryPoolModel(mbeanName, 
JmxModelFactory.getJmxModelFor((Application) super.getDataSource()), conn);
+            memoryPoolModels.add(model);
+        } catch (Exception e) {
             Exceptions.printStackTrace(e);
+        }
+    }
+
+    private void findGarbageCollectorsAndCreatePanels() {
+        findGarbageCollectors();
+        PanelPositions positions = new PanelPositions();
+        for (GarbageCollectorModel model : garbageCollectorModels) {
+            createGarbageCollectorPanelFor(model, positions);
+        }
+    }
+
+    protected void findGarbageCollectors() {
+        try {
+            MBeanServerConnection conn = 
getMBeanServerConnection((Application) super.getDataSource());
+            for (ObjectName name : 
conn.queryNames(Constants.GARBAGE_COLLECTOR_WILDCARD_PATTERN, null)) {
+                initializeGarbageCollectorModel(name, conn);
+            }
         } catch (IOException e) {
             Exceptions.printStackTrace(e);
         }
     }
 
-    /**
-     * For the current Oracle JVM 5 charts are displayed. Names seem to be
-     * fixed for the moment but can change. They are also different for other
-     * JVM OEMs. So if a name cannot be found in positions the solution is 
to stack
-     * the unknown charts  in the top left. This is under the assumption that
-     * if one is unknown, the lot is likely to be unknown and any attempt
-     * to come up with a semantically reasonable ordering will most likely 
-     * fail.
-     * 
-     * @param name
-     * @return 
-     */
-    private int corner = DataViewComponent.TOP_LEFT;
-    private int order = 1;
-    private Point calculatePosition(String name) {
-        Point point = positions.get(name);
-        if ( point == null) {
-            point = new Point( corner, order++);
-            corner = (corner == 5) ? 1 : corner++;
-        }
-        return point;
+    private void createGarbageCollectorPanelFor(GarbageCollectorModel model, 
PanelPositions positions) {
+        GarbageCollectorPanel panel = new 
GarbageCollectorPanel(model.getName());
+        model.registerView(panel);
+        Point position = positions.of(model.getName());
+        DataViewComponent.DetailsView detailsView = new 
DataViewComponent.DetailsView(
+                model.getName(), "garbage collector metrics", position.y, 
panel, null);
+        dvc.addDetailsView(detailsView, position.x);
     }
 
-    static {
-        positions = new HashMap<String,Point>();
-        positions.put( "Par Eden Space", new 
Point(DataViewComponent.TOP_LEFT,10));
-        positions.put( "PS Eden Space", new 
Point(DataViewComponent.TOP_LEFT,10));
-        positions.put( "Eden Space", new 
Point(DataViewComponent.TOP_LEFT,10));
-        positions.put( "G1 Eden", new Point(DataViewComponent.TOP_LEFT,10));
-        positions.put( "G1 Eden Space", new 
Point(DataViewComponent.TOP_LEFT,10));
-        positions.put( "Par Survivor Space", new 
Point(DataViewComponent.TOP_LEFT,20));
-        positions.put( "PS Survivor Space", new 
Point(DataViewComponent.TOP_LEFT,20));
-        positions.put( "Survivor Space", new 
Point(DataViewComponent.TOP_LEFT,20));
-        positions.put( "G1 Survivor", new 
Point(DataViewComponent.TOP_LEFT,20));
-        positions.put( "G1 Survivor Space", new 
Point(DataViewComponent.TOP_LEFT,20));
-        positions.put( "CMS Old Gen", new 
Point(DataViewComponent.TOP_RIGHT,10));
-        positions.put( "PS Old Gen", new 
Point(DataViewComponent.TOP_RIGHT,10));
-        positions.put( "Tenured Gen", new 
Point(DataViewComponent.TOP_RIGHT,10));
-        positions.put( "G1 Old Gen", new 
Point(DataViewComponent.TOP_RIGHT,10));
-        positions.put( "CMS Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT,10));
-        positions.put( "Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT,10));
-        positions.put( "PS Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT,10));
-        positions.put( "G1 Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT,10));
-        positions.put( "Code Cache", new 
Point(DataViewComponent.BOTTOM_RIGHT,10));
-        
-        //IBM Memory Pool Names
-        positions.put( "Java heap", new Point(DataViewComponent.TOP_LEFT, 
10));
-        positions.put( "class storage", new 
Point(DataViewComponent.TOP_RIGHT, 10));
-        positions.put( "miscellaneous non-heap storage", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
-        positions.put( "JIT code cache", new 
Point(DataViewComponent.BOTTOM_RIGHT, 10));
-        positions.put( "JIT data cache", new 
Point(DataViewComponent.BOTTOM_RIGHT, 20));
+    private void initializeGarbageCollectorModel(ObjectName mbeanName, 
MBeanServerConnection conn) {
+        try {
+            GarbageCollectorModel model = new 
GarbageCollectorModel(mbeanName, JmxModelFactory.getJmxModelFor((Application) 
super.getDataSource()), conn);
+            garbageCollectorModels.add(model);
+        } catch (Exception e) {
+            Exceptions.printStackTrace(e);
+        }
     }
 }
diff --git a/src/com/kodewerk/visualvm/memorypools/PanelPositions.java 
b/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
new file mode 100644
index 0000000..0da5694
--- /dev/null
+++ b/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
@@ -0,0 +1,68 @@
+package com.kodewerk.visualvm.memorypools;
+
+import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
+
+import java.awt.*;
+import java.util.HashMap;
+
+public class PanelPositions {
+    private final HashMap<String, Point> positions = new HashMap<String, 
Point>();
+
+    private int corner = DataViewComponent.TOP_LEFT;
+    private int order = 1;
+
+    public PanelPositions() {
+        // Hotspot Memory Pool Names
+        positions.put("Par Eden Space", new 
Point(DataViewComponent.TOP_LEFT, 10));
+        positions.put("PS Eden Space", new Point(DataViewComponent.TOP_LEFT, 
10));
+        positions.put("Eden Space", new Point(DataViewComponent.TOP_LEFT, 
10));
+        positions.put("G1 Eden", new Point(DataViewComponent.TOP_LEFT, 10));
+        positions.put("G1 Eden Space", new Point(DataViewComponent.TOP_LEFT, 
10));
+        positions.put("Par Survivor Space", new 
Point(DataViewComponent.TOP_LEFT, 20));
+        positions.put("PS Survivor Space", new 
Point(DataViewComponent.TOP_LEFT, 20));
+        positions.put("Survivor Space", new 
Point(DataViewComponent.TOP_LEFT, 20));
+        positions.put("G1 Survivor", new Point(DataViewComponent.TOP_LEFT, 
20));
+        positions.put("G1 Survivor Space", new 
Point(DataViewComponent.TOP_LEFT, 20));
+        positions.put("CMS Old Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
+        positions.put("PS Old Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
+        positions.put("Tenured Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
+        positions.put("G1 Old Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
+        positions.put("CMS Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
+        positions.put("Perm Gen", new Point(DataViewComponent.BOTTOM_LEFT, 
10));
+        positions.put("PS Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
+        positions.put("G1 Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
+        positions.put("Code Cache", new Point(DataViewComponent.BOTTOM_LEFT, 
10));
+
+        //IBM Memory Pool Names
+        positions.put("Java heap", new Point(DataViewComponent.TOP_LEFT, 
10));
+        positions.put("class storage", new 
Point(DataViewComponent.TOP_RIGHT, 10));
+        positions.put("miscellaneous non-heap storage", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
+        positions.put("JIT code cache", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
+        positions.put("JIT data cache", new 
Point(DataViewComponent.BOTTOM_LEFT, 20));
+
+        // Hotspot Garbage Collectors
+        positions.put("PS Scavenge", new 
Point(DataViewComponent.BOTTOM_RIGHT, 20));
+        positions.put("PS MarkSweep", new 
Point(DataViewComponent.BOTTOM_RIGHT, 20));
+    }
+
+    /**
+     * For the current Oracle JVM 5 charts are displayed. Names seem to be
+     * fixed for the moment but can change. They are also different for other
+     * JVM OEMs. So if a name cannot be found in positions the solution is 
to stack
+     * the unknown charts  in the top left. This is under the assumption that
+     * if one is unknown, the lot is likely to be unknown and any attempt
+     * to come up with a semantically reasonable ordering will most likely
+     * fail.
+     *
+     * @param name the name of the GC
+     * @return the associated position
+     */
+    public Point of(String name) {
+        Point point = positions.get(name);
+        if (point == null) {
+            point = new Point(corner, order++);
+            corner = (corner == 5) ? 1 : corner++;
+        }
+        return point;
+    }
+}
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
new file mode 100644
index 0000000..115253d
--- /dev/null
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
@@ -0,0 +1,89 @@
+package com.kodewerk.visualvm.memorypools.gc;
+
+import com.sun.tools.visualvm.tools.jmx.CachedMBeanServerConnectionFactory;
+import com.sun.tools.visualvm.tools.jmx.JmxModel;
+import com.sun.tools.visualvm.tools.jmx.MBeanCacheListener;
+import org.openide.util.Exceptions;
+
+import javax.management.*;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+public class GarbageCollectorModel implements MBeanCacheListener {
+    private Set<GarbageCollectorModelListener> listeners = new 
HashSet<GarbageCollectorModelListener>();
+
+    private final String name;
+    private final ObjectName mbeanName;
+    private final MBeanServerConnection mbeanServerConnection;
+
+    private Collections collections = new Collections(0, 0);
+
+    public GarbageCollectorModel(final ObjectName mbeanName, final JmxModel 
model, final MBeanServerConnection mbeanServerConnection) throws 
MBeanException, AttributeNotFoundException, InstanceNotFoundException, 
ReflectionException, IOException {
+        this.mbeanName = mbeanName;
+        this.mbeanServerConnection = mbeanServerConnection;
+        
CachedMBeanServerConnectionFactory.getCachedMBeanServerConnection(model, 
2000).addMBeanCacheListener(this);
+        name = mbeanServerConnection.getAttribute(mbeanName, 
"Name").toString();
+    }
+
+    @Override
+    public void flushed() {
+        try {
+            Long collectionTime = (Long) 
mbeanServerConnection.getAttribute(mbeanName, "CollectionTime");
+            Long collectionCount = (Long) 
mbeanServerConnection.getAttribute(mbeanName, "CollectionCount");
+            if (collections.differFrom(collectionTime, collectionCount)) {
+                this.collections = new Collections(collectionCount, 
collectionTime);
+                tickleListeners();
+            }
+        } catch (Throwable t) {
+            Exceptions.attachMessage(t, "Exception recovering data from 
MemoryPoolMXBean ");
+        }
+    }
+
+    private void tickleListeners() {
+        for (GarbageCollectorModelListener listener : listeners) {
+            listener.garbageCollectorUpdated(this);
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Collections getCollections() {
+        return collections;
+    }
+
+    public void registerView(GarbageCollectorModelListener listener) {
+        listeners.add(listener);
+    }
+
+    public class Collections {
+        private final long count;
+        private final long totalDuration;
+        private final long averageDuration;
+
+        public Collections(long count, long totalDuration) {
+            this.count = count;
+            this.totalDuration = totalDuration;
+            this.averageDuration = count != 0 ? totalDuration / count : 0;
+        }
+
+        public long getCount() {
+            return count;
+        }
+
+        public long getTotalDuration() {
+            return totalDuration;
+        }
+
+        public long getAverageDuration() {
+            return averageDuration;
+        }
+
+        public boolean differFrom(Long collectionTime, Long collectionCount) 
{
+            return collectionTime != null && collectionCount != null
+                    && !collectionCount.equals(count) && 
!collectionTime.equals(totalDuration);
+        }
+    }
+}
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModelListener.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModelListener.java
new file mode 100644
index 0000000..8cd8245
--- /dev/null
+++ 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModelListener.java
@@ -0,0 +1,5 @@
+package com.kodewerk.visualvm.memorypools.gc;
+
+public interface GarbageCollectorModelListener {
+    public void garbageCollectorUpdated(GarbageCollectorModel model);
+}
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
new file mode 100644
index 0000000..353b67a
--- /dev/null
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
@@ -0,0 +1,40 @@
+package com.kodewerk.visualvm.memorypools.gc;
+
+import com.kodewerk.visualvm.memorypools.Constants;
+import com.sun.tools.visualvm.charts.ChartFactory;
+import com.sun.tools.visualvm.charts.SimpleXYChartDescriptor;
+import com.sun.tools.visualvm.charts.SimpleXYChartSupport;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class GarbageCollectorPanel extends JPanel implements 
GarbageCollectorModelListener {
+    private SimpleXYChartSupport chart;
+
+    public GarbageCollectorPanel(String name) {
+        setLayout(new BorderLayout());
+        SimpleXYChartDescriptor description = 
SimpleXYChartDescriptor.decimal(Constants.ONE_MEGABYTE_SIZE, false, 1000);
+
+//        description.addLineItems("Last GC duration");
+        description.addLineItems("Average duration");
+        description.setDetailsItems(new String[]{"Last duration", "Number of 
collections", "Average duration"});
+
+        chart = ChartFactory.createSimpleXYChart(description);
+        add(chart.getChart(), BorderLayout.CENTER);
+    }
+
+    @Override
+    public void garbageCollectorUpdated(GarbageCollectorModel model) {
+        long[] dataPoints = new long[1];
+//          dataPoints[0] = model.getCollections().getTotalDuration();
+        dataPoints[0] = model.getCollections().getAverageDuration();
+        chart.addValues(System.currentTimeMillis(), dataPoints);
+
+        String[] details = new String[3];
+        details[0] = "Unknown";
+        details[1] = String.valueOf(model.getCollections().getCount());
+        details[2] = model.getCollections().getAverageDuration() + " ms";
+        chart.updateDetails(details);
+
+    }
+}
diff --git a/src/com/kodewerk/visualvm/memorypools/PanelPositions.java 
b/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
index 0da5694..9241ba7 100644
--- a/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
+++ b/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
@@ -27,16 +27,16 @@ public class PanelPositions {
         positions.put("PS Old Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
         positions.put("Tenured Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
         positions.put("G1 Old Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
-        positions.put("CMS Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
-        positions.put("Perm Gen", new Point(DataViewComponent.BOTTOM_LEFT, 
10));
-        positions.put("PS Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
-        positions.put("G1 Perm Gen", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
+        positions.put("CMS Perm Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
+        positions.put("Perm Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
+        positions.put("PS Perm Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
+        positions.put("G1 Perm Gen", new Point(DataViewComponent.TOP_RIGHT, 
10));
         positions.put("Code Cache", new Point(DataViewComponent.BOTTOM_LEFT, 
10));
 
         //IBM Memory Pool Names
         positions.put("Java heap", new Point(DataViewComponent.TOP_LEFT, 
10));
         positions.put("class storage", new 
Point(DataViewComponent.TOP_RIGHT, 10));
-        positions.put("miscellaneous non-heap storage", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
+        positions.put("miscellaneous non-heap storage", new 
Point(DataViewComponent.TOP_RIGHT, 10));
         positions.put("JIT code cache", new 
Point(DataViewComponent.BOTTOM_LEFT, 10));
         positions.put("JIT data cache", new 
Point(DataViewComponent.BOTTOM_LEFT, 20));
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
index 115253d..283bbdd 100644
--- a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
@@ -6,18 +6,19 @@ import com.sun.tools.visualvm.tools.jmx.MBeanCacheListener;
 import org.openide.util.Exceptions;
 
 import javax.management.*;
+import javax.management.openmbean.CompositeData;
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.Set;
 
 public class GarbageCollectorModel implements MBeanCacheListener {
-    private Set<GarbageCollectorModelListener> listeners = new 
HashSet<GarbageCollectorModelListener>();
 
+    private final Set<GarbageCollectorModelListener> listeners = new 
HashSet<GarbageCollectorModelListener>();
     private final String name;
     private final ObjectName mbeanName;
     private final MBeanServerConnection mbeanServerConnection;
 
-    private Collections collections = new Collections(0, 0);
+    private Collections collections = new Collections();
 
     public GarbageCollectorModel(final ObjectName mbeanName, final JmxModel 
model, final MBeanServerConnection mbeanServerConnection) throws 
MBeanException, AttributeNotFoundException, InstanceNotFoundException, 
ReflectionException, IOException {
         this.mbeanName = mbeanName;
@@ -31,12 +32,36 @@ public class GarbageCollectorModel implements 
MBeanCacheListener {
         try {
             Long collectionTime = (Long) 
mbeanServerConnection.getAttribute(mbeanName, "CollectionTime");
             Long collectionCount = (Long) 
mbeanServerConnection.getAttribute(mbeanName, "CollectionCount");
-            if (collections.differFrom(collectionTime, collectionCount)) {
-                this.collections = new Collections(collectionCount, 
collectionTime);
+            Long lastDuration = extractLastDuration();
+            if (collections.differFrom(collectionTime, collectionCount, 
lastDuration)) {
+                this.collections = new Collections(collectionCount, 
collectionTime, lastDuration);
                 tickleListeners();
             }
         } catch (Throwable t) {
-            Exceptions.attachMessage(t, "Exception recovering data from 
MemoryPoolMXBean ");
+            Exceptions.attachMessage(t, "Exception recovering data from 
GarbageCollectorMXBean");
+        }
+    }
+
+    private Long extractLastDuration() throws AttributeNotFoundException, 
MBeanException, ReflectionException, InstanceNotFoundException, IOException {
+        try {
+            return extractLastDurationFromHotspot();
+        } catch (AttributeNotFoundException e) {
+            return extractLastDurationFromJ9();
+        }
+    }
+
+    private Long extractLastDurationFromHotspot() throws 
AttributeNotFoundException, MBeanException, ReflectionException, 
InstanceNotFoundException, IOException {
+        CompositeData lastGcInfo = (CompositeData) 
mbeanServerConnection.getAttribute(mbeanName, "LastGcInfo");
+        return (Long) lastGcInfo.get("duration");
+    }
+
+    private Long extractLastDurationFromJ9() throws 
AttributeNotFoundException, MBeanException, ReflectionException, 
InstanceNotFoundException, IOException {
+        Long lastCollectionStartTime = (Long) 
mbeanServerConnection.getAttribute(mbeanName, "LastCollectionStartTime");
+        Long lastCollectionEndTime = (Long) 
mbeanServerConnection.getAttribute(mbeanName, "LastCollectionEndTime");
+        if (lastCollectionStartTime == null || lastCollectionEndTime == 
null) {
+            return null;
+        } else {
+            return lastCollectionEndTime - lastCollectionStartTime;
         }
     }
 
@@ -62,10 +87,16 @@ public class GarbageCollectorModel implements 
MBeanCacheListener {
         private final long count;
         private final long totalDuration;
         private final long averageDuration;
+        private final long lastDuration;
+
+        public Collections() {
+            this(0, 0, 0);
+        }
 
-        public Collections(long count, long totalDuration) {
+        public Collections(long count, long totalDuration, long 
lastDuration) {
             this.count = count;
             this.totalDuration = totalDuration;
+            this.lastDuration = lastDuration;
             this.averageDuration = count != 0 ? totalDuration / count : 0;
         }
 
@@ -81,8 +112,12 @@ public class GarbageCollectorModel implements 
MBeanCacheListener {
             return averageDuration;
         }
 
-        public boolean differFrom(Long collectionTime, Long collectionCount) 
{
-            return collectionTime != null && collectionCount != null
+        public long getLastDuration() {
+            return lastDuration;
+        }
+
+        public boolean differFrom(Long collectionTime, Long collectionCount, 
Long lastDuration) {
+            return collectionTime != null && collectionCount != null && 
lastDuration != null
                     && !collectionCount.equals(count) && 
!collectionTime.equals(totalDuration);
         }
     }
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
index 353b67a..0cd2f21 100644
--- a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
@@ -15,9 +15,9 @@ public class GarbageCollectorPanel extends JPanel 
implements GarbageCollectorMod
         setLayout(new BorderLayout());
         SimpleXYChartDescriptor description = 
SimpleXYChartDescriptor.decimal(Constants.ONE_MEGABYTE_SIZE, false, 1000);
 
-//        description.addLineItems("Last GC duration");
+        description.addLineItems("Last GC duration");
         description.addLineItems("Average duration");
-        description.setDetailsItems(new String[]{"Last duration", "Number of 
collections", "Average duration"});
+        description.setDetailsItems(new String[]{"Last duration", "Number of 
collections", "Average duration", "Total time in GC"});
 
         chart = ChartFactory.createSimpleXYChart(description);
         add(chart.getChart(), BorderLayout.CENTER);
@@ -25,16 +25,16 @@ public class GarbageCollectorPanel extends JPanel 
implements GarbageCollectorMod
 
     @Override
     public void garbageCollectorUpdated(GarbageCollectorModel model) {
-        long[] dataPoints = new long[1];
-//          dataPoints[0] = model.getCollections().getTotalDuration();
-        dataPoints[0] = model.getCollections().getAverageDuration();
+        long[] dataPoints = new long[2];
+        dataPoints[0] = model.getCollections().getLastDuration();
+        dataPoints[1] = model.getCollections().getAverageDuration();
         chart.addValues(System.currentTimeMillis(), dataPoints);
 
-        String[] details = new String[3];
-        details[0] = "Unknown";
+        String[] details = new String[4];
+        details[0] = model.getCollections().getLastDuration() + " ms";
         details[1] = String.valueOf(model.getCollections().getCount());
         details[2] = model.getCollections().getAverageDuration() + " ms";
+        details[3] = model.getCollections().getTotalDuration() + " ms";
         chart.updateDetails(details);
-
     }
 }
diff --git a/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java 
b/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
index d45fd02..2677694 100644
--- a/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
+++ b/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
@@ -33,13 +33,15 @@ import javax.swing.*;
 import java.awt.*;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Set;
+import java.util.TreeSet;
 
 /**
  * @author kirk
  */
 class MemoryPoolView extends DataSourceView {
     private ArrayList<MemoryPoolModel> memoryPoolModels = new 
ArrayList<MemoryPoolModel>();
-    private ArrayList<GarbageCollectorModel> garbageCollectorModels = new 
ArrayList<GarbageCollectorModel>();
+    private Set<GarbageCollectorModel> garbageCollectorModels = new 
TreeSet<GarbageCollectorModel>(GarbageCollectorModel.compareOnGeneration());
     private DataViewComponent dvc;
 
     public MemoryPoolView(Application application) {
diff --git a/src/com/kodewerk/visualvm/memorypools/gc/Collections.java 
b/src/com/kodewerk/visualvm/memorypools/gc/Collections.java
new file mode 100644
index 0000000..a0f7be5
--- /dev/null
+++ b/src/com/kodewerk/visualvm/memorypools/gc/Collections.java
@@ -0,0 +1,40 @@
+package com.kodewerk.visualvm.memorypools.gc;
+
+public class Collections {
+    private final long count;
+    private final long totalDuration;
+    private final long averageDuration;
+    private final long lastDuration;
+
+    public Collections() {
+        this(0, 0, 0);
+    }
+
+    public Collections(long count, long totalDuration, long lastDuration) {
+        this.count = count;
+        this.totalDuration = totalDuration;
+        this.lastDuration = lastDuration;
+        this.averageDuration = count != 0 ? totalDuration / count : 0;
+    }
+
+    public long getCount() {
+        return count;
+    }
+
+    public long getTotalDuration() {
+        return totalDuration;
+    }
+
+    public long getAverageDuration() {
+        return averageDuration;
+    }
+
+    public long getLastDuration() {
+        return lastDuration;
+    }
+
+    public boolean differFrom(Long collectionTime, Long collectionCount, 
Long lastDuration) {
+        return collectionTime != null && collectionCount != null && 
lastDuration != null
+                && !collectionCount.equals(count);
+    }
+}
diff --git a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollector.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollector.java
new file mode 100644
index 0000000..a8fa065
--- /dev/null
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollector.java
@@ -0,0 +1,28 @@
+package com.kodewerk.visualvm.memorypools.gc;
+
+public enum GarbageCollector {
+    PS_SCAVENGE("PS Scavenge", Generation.YOUNG)
+    , PS_MARK_SWEEP("PS MarkSweep", Generation.OLD)
+    ;
+
+    private final String name;
+    private final Generation generation;
+
+    GarbageCollector(String name, Generation generation) {
+        this.name = name;
+        this.generation = generation;
+    }
+
+    public Generation getGeneration() {
+        return generation;
+    }
+
+    static GarbageCollector fromName(String name) {
+        for (GarbageCollector garbageCollector : values()) {
+            if(garbageCollector.name.equals(name)) {
+                return garbageCollector;
+            }
+        }
+        return null;
+    }
+}
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
index 283bbdd..000d741 100644
--- a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
@@ -8,6 +8,7 @@ import org.openide.util.Exceptions;
 import javax.management.*;
 import javax.management.openmbean.CompositeData;
 import java.io.IOException;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -17,6 +18,7 @@ public class GarbageCollectorModel implements 
MBeanCacheListener {
     private final String name;
     private final ObjectName mbeanName;
     private final MBeanServerConnection mbeanServerConnection;
+    private final GarbageCollector garbageCollector;
 
     private Collections collections = new Collections();
 
@@ -25,6 +27,7 @@ public class GarbageCollectorModel implements 
MBeanCacheListener {
         this.mbeanServerConnection = mbeanServerConnection;
         
CachedMBeanServerConnectionFactory.getCachedMBeanServerConnection(model, 
2000).addMBeanCacheListener(this);
         name = mbeanServerConnection.getAttribute(mbeanName, 
"Name").toString();
+        garbageCollector = GarbageCollector.fromName(name);
     }
 
     @Override
@@ -83,42 +86,22 @@ public class GarbageCollectorModel implements 
MBeanCacheListener {
         listeners.add(listener);
     }
 
-    public class Collections {
-        private final long count;
-        private final long totalDuration;
-        private final long averageDuration;
-        private final long lastDuration;
-
-        public Collections() {
-            this(0, 0, 0);
-        }
-
-        public Collections(long count, long totalDuration, long 
lastDuration) {
-            this.count = count;
-            this.totalDuration = totalDuration;
-            this.lastDuration = lastDuration;
-            this.averageDuration = count != 0 ? totalDuration / count : 0;
-        }
-
-        public long getCount() {
-            return count;
-        }
-
-        public long getTotalDuration() {
-            return totalDuration;
-        }
-
-        public long getAverageDuration() {
-            return averageDuration;
-        }
-
-        public long getLastDuration() {
-            return lastDuration;
-        }
+    public GarbageCollector getGarbageCollector() {
+        return garbageCollector;
+    }
 
-        public boolean differFrom(Long collectionTime, Long collectionCount, 
Long lastDuration) {
-            return collectionTime != null && collectionCount != null && 
lastDuration != null
-                    && !collectionCount.equals(count) && 
!collectionTime.equals(totalDuration);
-        }
+    public static Comparator<GarbageCollectorModel> compareOnGeneration() {
+        return new Comparator<GarbageCollectorModel>() {
+            @Override
+            public int compare(GarbageCollectorModel o1, 
GarbageCollectorModel o2) {
+                // This method does not respect the general contract of 
compare in Comparable
+                // However, since we cannot have two GC for the same 
generation in a JVM, this method does the job
+                if(o1.garbageCollector.getGeneration() == Generation.YOUNG) {
+                    return -1;
+                } else {
+                    return 1;
+                }
+            }
+        };
     }
 }
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
index 0cd2f21..c54e7da 100644
--- a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
@@ -7,6 +7,10 @@ import com.sun.tools.visualvm.charts.SimpleXYChartSupport;
 
 import javax.swing.*;
 import java.awt.*;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
 
 public class GarbageCollectorPanel extends JPanel implements 
GarbageCollectorModelListener {
     private SimpleXYChartSupport chart;
@@ -31,10 +35,17 @@ public class GarbageCollectorPanel extends JPanel 
implements GarbageCollectorMod
         chart.addValues(System.currentTimeMillis(), dataPoints);
 
         String[] details = new String[4];
-        details[0] = model.getCollections().getLastDuration() + " ms";
+        details[0] = formatNumber(model.getCollections().getLastDuration()) 
+ " ms";
         details[1] = String.valueOf(model.getCollections().getCount());
-        details[2] = model.getCollections().getAverageDuration() + " ms";
-        details[3] = model.getCollections().getTotalDuration() + " ms";
+        details[2] = 
formatNumber(model.getCollections().getAverageDuration()) + " ms";
+        details[3] = formatNumber(model.getCollections().getTotalDuration()) 
+ " ms";
         chart.updateDetails(details);
     }
+
+    public String formatNumber(long number) {
+        DecimalFormat formatter = (DecimalFormat) 
NumberFormat.getInstance(new Locale("en_US"));
+        DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols();
+        symbols.setGroupingSeparator(' ');
+        return formatter.format(number);
+    }
 }
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorSummaryPanel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorSummaryPanel.java
new file mode 100644
index 0000000..aaa2db3
--- /dev/null
+++ 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorSummaryPanel.java
@@ -0,0 +1,4 @@
+package com.kodewerk.visualvm.memorypools.gc;
+
+public class GarbageCollectorSummaryPanel {
+}
diff --git a/src/com/kodewerk/visualvm/memorypools/gc/Generation.java 
b/src/com/kodewerk/visualvm/memorypools/gc/Generation.java
new file mode 100644
index 0000000..51167b2
--- /dev/null
+++ b/src/com/kodewerk/visualvm/memorypools/gc/Generation.java
@@ -0,0 +1,5 @@
+package com.kodewerk.visualvm.memorypools.gc;
+
+public enum Generation {
+    YOUNG, OLD
+}
diff --git a/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java 
b/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
index 2677694..5688f5b 100644
--- a/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
+++ b/src/com/kodewerk/visualvm/memorypools/MemoryPoolView.java
@@ -19,6 +19,7 @@ package com.kodewerk.visualvm.memorypools;
 
 import com.kodewerk.visualvm.memorypools.gc.GarbageCollectorModel;
 import com.kodewerk.visualvm.memorypools.gc.GarbageCollectorPanel;
+import com.kodewerk.visualvm.memorypools.gc.GarbageCollectorSummaryPanel;
 import com.sun.tools.visualvm.application.Application;
 import com.sun.tools.visualvm.core.ui.DataSourceView;
 import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
@@ -30,6 +31,7 @@ import org.openide.util.ImageUtilities;
 import javax.management.MBeanServerConnection;
 import javax.management.ObjectName;
 import javax.swing.*;
+import javax.swing.border.EmptyBorder;
 import java.awt.*;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -40,8 +42,8 @@ import java.util.TreeSet;
  * @author kirk
  */
 class MemoryPoolView extends DataSourceView {
-    private ArrayList<MemoryPoolModel> memoryPoolModels = new 
ArrayList<MemoryPoolModel>();
-    private Set<GarbageCollectorModel> garbageCollectorModels = new 
TreeSet<GarbageCollectorModel>(GarbageCollectorModel.compareOnGeneration());
+    private final ArrayList<MemoryPoolModel> memoryPoolModels = new 
ArrayList<MemoryPoolModel>();
+    private final Set<GarbageCollectorModel> garbageCollectorModels = new 
TreeSet<GarbageCollectorModel>(GarbageCollectorModel.compareOnGeneration());
     private DataViewComponent dvc;
 
     public MemoryPoolView(Application application) {
@@ -115,11 +117,31 @@ class MemoryPoolView extends DataSourceView {
     private void findGarbageCollectorsAndCreatePanels() {
         findGarbageCollectors();
         PanelPositions positions = new PanelPositions();
+        createGarbageCollectorSummaryPanel(garbageCollectorModels, 
positions);
         for (GarbageCollectorModel model : garbageCollectorModels) {
             createGarbageCollectorPanelFor(model, positions);
         }
     }
 
+    private void 
createGarbageCollectorSummaryPanel(Set<GarbageCollectorModel> 
garbageCollectorModels, PanelPositions positions) {
+        JPanel groupPanel = new JPanel();
+        groupPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
+        groupPanel.setOpaque(false);
+        groupPanel.setLayout(new BoxLayout(groupPanel, BoxLayout.Y_AXIS));
+        for (GarbageCollectorModel garbageCollectorModel : 
garbageCollectorModels) {
+            GarbageCollectorSummaryPanel summaryPanel = new 
GarbageCollectorSummaryPanel(garbageCollectorModel.getName());
+            garbageCollectorModel.registerView(summaryPanel);
+
+            groupPanel.add(summaryPanel);
+            groupPanel.add(Box.createVerticalGlue());
+        }
+
+        Point position = positions.of("GC Summary Panel");
+        DataViewComponent.DetailsView detailsView = new 
DataViewComponent.DetailsView(
+                "GC Summary Panel", "Garbage Collectors summary panel", 
position.y, groupPanel, null);
+        dvc.addDetailsView(detailsView, position.x);
+    }
+
     protected void findGarbageCollectors() {
         try {
             MBeanServerConnection conn = 
getMBeanServerConnection((Application) super.getDataSource());
diff --git a/src/com/kodewerk/visualvm/memorypools/PanelPositions.java 
b/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
index 9241ba7..4b3eb4c 100644
--- a/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
+++ b/src/com/kodewerk/visualvm/memorypools/PanelPositions.java
@@ -41,8 +41,10 @@ public class PanelPositions {
         positions.put("JIT data cache", new 
Point(DataViewComponent.BOTTOM_LEFT, 20));
 
         // Hotspot Garbage Collectors
+        positions.put("GC Summary Panel", new 
Point(DataViewComponent.BOTTOM_RIGHT, 20));
         positions.put("PS Scavenge", new 
Point(DataViewComponent.BOTTOM_RIGHT, 20));
         positions.put("PS MarkSweep", new 
Point(DataViewComponent.BOTTOM_RIGHT, 20));
+
     }
 
     /**
diff --git a/src/com/kodewerk/visualvm/memorypools/gc/Collections.java 
b/src/com/kodewerk/visualvm/memorypools/gc/Collections.java
index a0f7be5..0b9c837 100644
--- a/src/com/kodewerk/visualvm/memorypools/gc/Collections.java
+++ b/src/com/kodewerk/visualvm/memorypools/gc/Collections.java
@@ -1,5 +1,10 @@
 package com.kodewerk.visualvm.memorypools.gc;
 
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+
 public class Collections {
     private final long count;
     private final long totalDuration;
@@ -37,4 +42,11 @@ public class Collections {
         return collectionTime != null && collectionCount != null && 
lastDuration != null
                 && !collectionCount.equals(count);
     }
+
+    public static String formatNumber(long number) {
+        DecimalFormat formatter = (DecimalFormat) 
NumberFormat.getInstance(new Locale("en_US"));
+        DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols();
+        symbols.setGroupingSeparator(' ');
+        return formatter.format(number);
+    }
 }
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
index 000d741..87d87dc 100644
--- a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorModel.java
@@ -78,16 +78,24 @@ public class GarbageCollectorModel implements 
MBeanCacheListener {
         return name;
     }
 
-    public Collections getCollections() {
-        return collections;
+    public long getCount() {
+        return collections.getCount();
     }
 
-    public void registerView(GarbageCollectorModelListener listener) {
-        listeners.add(listener);
+    public long getTotalDuration() {
+        return collections.getTotalDuration();
+    }
+
+    public long getAverageDuration() {
+        return collections.getAverageDuration();
     }
 
-    public GarbageCollector getGarbageCollector() {
-        return garbageCollector;
+    public long getLastDuration() {
+        return collections.getLastDuration();
+    }
+
+    public void registerView(GarbageCollectorModelListener listener) {
+        listeners.add(listener);
     }
 
     public static Comparator<GarbageCollectorModel> compareOnGeneration() {
diff --git 
a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java 
b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
index c54e7da..1ff524a 100644
--- a/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
+++ b/src/com/kodewerk/visualvm/memorypools/gc/GarbageCollectorPanel.java
@@ -7,10 +7,6 @@ import com.sun.tools.visualvm.charts.SimpleXYChartSupport;
 
 import javax.swing.*;
 import java.awt.*;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.NumberFormat;
-import java.util.Locale;
 
 public class GarbageCollectorPanel extends JPanel implements 
GarbageCollectorModelListener {
     private SimpleXYChartSupport chart;
@@ -30,22 +26,15 @@ public class GarbageCollectorPanel extends JPanel 
implements GarbageCollectorMod
     @Override
     public void garbageCollectorUpdated(GarbageCollectorModel model) {
         long[] dataPoints = new long[2];
-        dataPoints[0] = model.getCollections().getLastDuration();
-        dataPoints[1] = model.getCollections().getAverageDuration();
+        dataPoints[0] = model.getLastDuration();
+        dataPoints[1] = model.getAverageDuration();
         chart.addValues(System.currentTimeMillis(), dataPoints);
 
         String[] details = new String[4];
-        details[0] = formatNumber(model.getCollections().getLastDuration()) 
+ " ms";
-        details[1] = String.valueOf(model.getCollections().getCount());
-        details[2] = 
formatNumber(model.getCollections().getAverageDuration()) + " ms";
-        details[3] = formatNumber(model.getCollections().getTotalDuration()) 
+ " ms";
+        details[0] = Collections.formatNumber(model.getLastDuration()) + " 
ms";
+        details[1] = String.valueOf(model.getCount());
+        details[2] = Collections.formatNumber(model.getAverageDuration()) + 
" ms";
+        details[3] = Coll
[truncated due to length]



[memorypoolview~source-code-repository:87d7355d] Updated copyright

pingtimeout 03/19/2013

<Possible follow-up(s)>

[memorypoolview~source-code-repository:87d7355d] Updated copyright

pingtimeout 03/25/2013
 
 
Close
loading
Please Confirm
Close