code.google.gclogviewer.GCLogViewer.java Source code

Java tutorial

Introduction

Here is the source code for code.google.gclogviewer.GCLogViewer.java

Source

/**
 * GCLogViewer
 * 
 * A free open source tool to visualize data produced by the Java VM options -Xloggc:<file> or jstat > <file>.
 * 
 * Code license:   Apache License 2.0
 * 
 * http://code.google.com/p/gclogviewer
 */
package code.google.gclogviewer;

import java.text.DecimalFormat;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.experimental.chart.swt.ChartComposite;
import org.jfree.ui.RectangleInsets;

/**
 * GCLogViewer,create shell/generate chart graph/handle ui event
 * 
 * @author <a href="mailto:bluedavy@gmail.com">bluedavy</a>
 */
public class GCLogViewer {

    private static final String[] FILTER_NAMES = { "GC Log File (*.log)", "All Files (*.*)" };
    private static final String[] FILTER_EXTS = { "*.log", "*.*" };

    private static final String SHELL_TITLE = "GCLogViewer";

    private Shell shell = null;
    private Menu menuBar, fileMenu, toolsMenu;
    private MenuItem fileMenuHeader, toolsMenuItem, fileOpenMenuItem;
    private MenuItem memoryLeakDetectionMenuItem, gcTuningMenuItem, compareLogMenuItem, exportToPDFMenuItem;
    private MenuItem exitMenuItem, backToHomeMenuItem;
    private Group summary = null, gcTrendGroup = null, memoryTrendGroup = null;
    private Label runtimedataLabel;
    private Label gctypedataLabel;
    private Label throughputdataLabel;
    private Label ygcDataLabel, ygctDataLabel, avgYGCTDataLabel, avgYGCRateDataLabel;
    private Label fgcDataLabel, fgctDataLabel, avgFGCTDataLabel, avgFGCRateDataLabel;
    private Label cmsgcDataLabel, cmsgctDataLabel, avgCMSGCTDataLabel, avgCMSGCRateDataLabel;
    private Label avgYGCLDSDataLabel, avgFGCLDSDataLabel, avgPTOSDataLabel;
    private ChartComposite gcTrendChart = null, memoryTrendChart = null;
    private ProgressBar bar;
    private final GCLogAnalyze analyze = new GCLogAnalyze();
    private GCLogData currentGCLogData = null;
    private String currentGCLogFile = null;

    public static void main(String[] args) {
        Display display = Display.getDefault();
        GCLogViewer thisClass = new GCLogViewer();
        thisClass.createShell();
        thisClass.shell.open();

        while (!thisClass.shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }

    private void createShell() {
        shell = new Shell(SWT.SHELL_TRIM | SWT.APPLICATION_MODAL);
        shell.setText(SHELL_TITLE);
        shell.setBackground(new Color(Display.getCurrent(), 255, 255, 255));
        shell.setMaximized(false);
        shell.setToolTipText(
                "A free open source tool to visualize data produced by the Java VM options -Xloggc:<file>");
        Monitor primary = shell.getDisplay().getPrimaryMonitor();
        Rectangle bounds = primary.getBounds();
        shell.setSize(new Point(bounds.width - 100, bounds.height - 100));
        Rectangle rect = shell.getBounds();
        int x = bounds.x + (bounds.width - rect.width) / 2;
        int y = bounds.y + (bounds.height - rect.height) / 2;
        shell.setLocation(x, y);
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        shell.setLayout(layout);

        menuBar = new Menu(shell, SWT.BAR);
        fileMenuHeader = new MenuItem(menuBar, SWT.CASCADE);
        fileMenuHeader.setText("&File");
        toolsMenuItem = new MenuItem(menuBar, SWT.CASCADE);
        toolsMenuItem.setText("&Tools");
        backToHomeMenuItem = new MenuItem(menuBar, SWT.CASCADE);
        backToHomeMenuItem.setText("Back To Home");
        backToHomeMenuItem.setEnabled(false);
        backToHomeMenuItem.addSelectionListener(new BackToHomeListener());
        exitMenuItem = new MenuItem(menuBar, SWT.CASCADE);
        exitMenuItem.setText("&Exit");
        exitMenuItem.addSelectionListener(new ExitListener());

        fileMenu = new Menu(shell, SWT.DROP_DOWN);
        fileMenuHeader.setMenu(fileMenu);

        fileOpenMenuItem = new MenuItem(fileMenu, SWT.PUSH);
        fileOpenMenuItem.setText("&Open log file...");
        fileOpenMenuItem.addSelectionListener(new OpenFileListener());

        toolsMenu = new Menu(shell, SWT.DROP_DOWN);
        toolsMenuItem.setMenu(toolsMenu);

        compareLogMenuItem = new MenuItem(toolsMenu, SWT.PUSH);
        compareLogMenuItem.setText("Compare GC Log");
        compareLogMenuItem.setEnabled(false);
        compareLogMenuItem.addSelectionListener(new CompareLogListener());
        memoryLeakDetectionMenuItem = new MenuItem(toolsMenu, SWT.PUSH);
        memoryLeakDetectionMenuItem.setText("Memory Leak Detection");
        memoryLeakDetectionMenuItem.setEnabled(false);
        memoryLeakDetectionMenuItem.addSelectionListener(new MemoryLeakDetectionListener());
        gcTuningMenuItem = new MenuItem(toolsMenu, SWT.PUSH);
        gcTuningMenuItem.setText("Data for GC Tuning");
        gcTuningMenuItem.setEnabled(false);
        gcTuningMenuItem.addSelectionListener(new DataForGCTuningListener());
        exportToPDFMenuItem = new MenuItem(toolsMenu, SWT.PUSH);
        exportToPDFMenuItem.setText("Export to PDF");
        exportToPDFMenuItem.setEnabled(false);

        shell.setMenuBar(menuBar);

        createSummary();
        createGCTrendGroup();
        createMemoryTrendGroup();
        createProgressBar();

        // Info Grid
        GridData infoGrid = new GridData(GridData.FILL_BOTH);
        final Label runtimeLabel = new Label(summary, SWT.NONE);
        runtimeLabel.setText("Run time: ");
        runtimeLabel.setLayoutData(infoGrid);
        runtimedataLabel = new Label(summary, SWT.NONE);
        runtimedataLabel.setText("xxx seconds");
        runtimedataLabel.setLayoutData(infoGrid);
        final Label gctypeLabel = new Label(summary, SWT.NONE);
        gctypeLabel.setText("GC Type: ");
        gctypeLabel.setLayoutData(infoGrid);
        gctypedataLabel = new Label(summary, SWT.NONE);
        gctypedataLabel.setText("xxx");
        gctypedataLabel.setLayoutData(infoGrid);
        final Label throughputLabel = new Label(summary, SWT.NONE);
        throughputLabel.setText("Throughput: ");
        throughputLabel.setLayoutData(infoGrid);
        throughputdataLabel = new Label(summary, SWT.NONE);
        throughputdataLabel.setText("xx%");
        throughputdataLabel.setLayoutData(infoGrid);
        final Label emptyLabel = new Label(summary, SWT.NONE);
        emptyLabel.setText(" ");
        emptyLabel.setLayoutData(infoGrid);
        final Label emptyDataLabel = new Label(summary, SWT.NONE);
        emptyDataLabel.setText(" ");
        emptyDataLabel.setLayoutData(infoGrid);

        // YGC Grid
        GridData ygcInfoGrid = new GridData(GridData.FILL_BOTH);
        final Label ygcLabel = new Label(summary, SWT.NONE);
        ygcLabel.setText("YGC: ");
        ygcLabel.setLayoutData(ygcInfoGrid);
        ygcDataLabel = new Label(summary, SWT.NONE);
        ygcDataLabel.setText("xxx");
        ygcDataLabel.setLayoutData(ygcInfoGrid);
        final Label ygctLabel = new Label(summary, SWT.NONE);
        ygctLabel.setText("YGCT: ");
        ygctLabel.setLayoutData(ygcInfoGrid);
        ygctDataLabel = new Label(summary, SWT.NONE);
        ygctDataLabel.setText("xxx seconds");
        ygctDataLabel.setLayoutData(ygcInfoGrid);
        final Label avgYGCTLabel = new Label(summary, SWT.NONE);
        avgYGCTLabel.setText("Avg YGCT: ");
        avgYGCTLabel.setLayoutData(ygcInfoGrid);
        avgYGCTDataLabel = new Label(summary, SWT.NONE);
        avgYGCTDataLabel.setText("xxx seconds");
        avgYGCTDataLabel.setLayoutData(ygcInfoGrid);
        final Label avgYGCRateLabel = new Label(summary, SWT.NONE);
        avgYGCRateLabel.setText("Avg YGCRate: ");
        avgYGCRateLabel.setLayoutData(ygcInfoGrid);
        avgYGCRateDataLabel = new Label(summary, SWT.NONE);
        avgYGCRateDataLabel.setText("xxx seconds");
        avgYGCRateDataLabel.setLayoutData(ygcInfoGrid);

        // CMS Grid
        GridData cmsgcInfoGrid = new GridData(GridData.FILL_BOTH);
        cmsgcInfoGrid.exclude = true;
        final Label cmsgcLabel = new Label(summary, SWT.NONE);
        cmsgcLabel.setText("CMSGC: ");
        cmsgcLabel.setLayoutData(cmsgcInfoGrid);
        cmsgcDataLabel = new Label(summary, SWT.NONE);
        cmsgcDataLabel.setText("xxx");
        cmsgcDataLabel.setLayoutData(cmsgcInfoGrid);
        final Label cmsgctLabel = new Label(summary, SWT.NONE);
        cmsgctLabel.setText("CMSGCT: ");
        cmsgctLabel.setLayoutData(cmsgcInfoGrid);
        cmsgctDataLabel = new Label(summary, SWT.NONE);
        cmsgctDataLabel.setText("xxx seconds");
        cmsgctDataLabel.setLayoutData(cmsgcInfoGrid);
        final Label avgCMSGCTLabel = new Label(summary, SWT.NONE);
        avgCMSGCTLabel.setText("Avg CMSGCT: ");
        avgCMSGCTLabel.setLayoutData(cmsgcInfoGrid);
        avgCMSGCTDataLabel = new Label(summary, SWT.NONE);
        avgCMSGCTDataLabel.setText("xxx seconds");
        avgCMSGCTDataLabel.setLayoutData(cmsgcInfoGrid);
        final Label avgCMSGCRateLabel = new Label(summary, SWT.NONE);
        avgCMSGCRateLabel.setText("Avg CMSGCRate: ");
        avgCMSGCRateLabel.setLayoutData(cmsgcInfoGrid);
        avgCMSGCRateDataLabel = new Label(summary, SWT.NONE);
        avgCMSGCRateDataLabel.setText("xxx seconds");
        avgCMSGCRateDataLabel.setLayoutData(cmsgcInfoGrid);

        // LDS & PTOS Grid
        GridData ldsAndPTOSGrid = new GridData(GridData.FILL_BOTH);
        ldsAndPTOSGrid.exclude = true;
        final Label avgYGCLDSLabel = new Label(summary, SWT.NONE);
        avgYGCLDSLabel.setText("AVG YGCLDS: ");
        avgYGCLDSLabel.setLayoutData(ldsAndPTOSGrid);
        avgYGCLDSDataLabel = new Label(summary, SWT.NONE);
        avgYGCLDSDataLabel.setText("xxx(K)");
        avgYGCLDSDataLabel.setLayoutData(ldsAndPTOSGrid);
        final Label avgFGCLDSLabel = new Label(summary, SWT.NONE);
        avgFGCLDSLabel.setText("AVG FGCLDS: ");
        avgFGCLDSLabel.setLayoutData(ldsAndPTOSGrid);
        avgFGCLDSDataLabel = new Label(summary, SWT.NONE);
        avgFGCLDSDataLabel.setText("xxx(K)");
        avgFGCLDSDataLabel.setLayoutData(ldsAndPTOSGrid);
        final Label avgPTOSLabel = new Label(summary, SWT.NONE);
        avgPTOSLabel.setText("AVG PTOS: ");
        avgPTOSLabel.setLayoutData(ldsAndPTOSGrid);
        avgPTOSDataLabel = new Label(summary, SWT.NONE);
        avgPTOSDataLabel.setText("xx%");
        avgPTOSDataLabel.setLayoutData(ldsAndPTOSGrid);
        final Label emptyLabel2 = new Label(summary, SWT.NONE);
        emptyLabel2.setText(" ");
        emptyLabel2.setLayoutData(ldsAndPTOSGrid);
        final Label emptyDataLabel2 = new Label(summary, SWT.NONE);
        emptyDataLabel2.setText(" ");
        emptyDataLabel2.setLayoutData(ldsAndPTOSGrid);

        // FGC Grid
        GridData fgcInfoGrid = new GridData(GridData.FILL_BOTH);
        final Label fgcLabel = new Label(summary, SWT.NONE);
        fgcLabel.setText("FGC: ");
        fgcLabel.setLayoutData(fgcInfoGrid);
        fgcDataLabel = new Label(summary, SWT.NONE);
        fgcDataLabel.setText("xxx");
        fgcDataLabel.setLayoutData(fgcInfoGrid);
        final Label fgctLabel = new Label(summary, SWT.NONE);
        fgctLabel.setText("FGCT: ");
        fgctLabel.setLayoutData(fgcInfoGrid);
        fgctDataLabel = new Label(summary, SWT.NONE);
        fgctDataLabel.setText("xxx seconds");
        fgctDataLabel.setLayoutData(fgcInfoGrid);
        final Label avgFGCTLabel = new Label(summary, SWT.NONE);
        avgFGCTLabel.setText("Avg FGCT: ");
        avgFGCTLabel.setLayoutData(fgcInfoGrid);
        avgFGCTDataLabel = new Label(summary, SWT.NONE);
        avgFGCTDataLabel.setText("xxx seconds");
        avgFGCTDataLabel.setLayoutData(fgcInfoGrid);
        final Label avgFGCRateLabel = new Label(summary, SWT.NONE);
        avgFGCRateLabel.setText("Avg FGCRate: ");
        avgFGCRateLabel.setLayoutData(fgcInfoGrid);
        avgFGCRateDataLabel = new Label(summary, SWT.NONE);
        avgFGCRateDataLabel.setText("xxx seconds");
        avgFGCRateDataLabel.setLayoutData(fgcInfoGrid);

    }

    private void createSummary() {
        summary = new Group(shell, SWT.NONE);
        summary.setText("Summary");
        GridData grid = new GridData(GridData.FILL_BOTH);
        grid.heightHint = shell.getDisplay().getBounds().height / 5;
        summary.setLayoutData(grid);
        GridLayout layout = new GridLayout();
        layout.numColumns = 8;
        layout.makeColumnsEqualWidth = true;
        summary.setLayout(layout);
    }

    private void createGCTrendGroup() {
        gcTrendGroup = new Group(shell, SWT.NONE);
        gcTrendGroup.setText("GC Trend");
        GridData grid = new GridData(GridData.FILL_BOTH);
        grid.heightHint = shell.getDisplay().getBounds().height * 4 / 10;
        gcTrendGroup.setLayoutData(grid);
        gcTrendGroup.setLayout(new GridLayout());
    }

    private void createMemoryTrendGroup() {
        memoryTrendGroup = new Group(shell, SWT.NONE);
        memoryTrendGroup.setText("Memory Trend");
        GridData grid = new GridData(GridData.FILL_BOTH);
        grid.heightHint = shell.getDisplay().getBounds().height * 4 / 10;
        memoryTrendGroup.setLayoutData(grid);
        memoryTrendGroup.setLayout(new GridLayout());
    }

    private void createProgressBar() {
        bar = new ProgressBar(shell, SWT.NONE | SWT.SMOOTH);
        bar.setMinimum(0);
        bar.setMaximum(100);
        GridData grid = new GridData(GridData.FILL_BOTH);
        grid.heightHint = shell.getDisplay().getBounds().height / 10;
        grid.exclude = true;
        bar.setLayoutData(grid);
    }

    private JFreeChart createGCTrendChart(GCLogData data) {
        XYDataset gcTrendDataset = createGCTrendDataset(data, null);
        JFreeChart chart = ChartFactory.createXYLineChart("GC Trend", "Time(S)", "Pause Time(ms)", gcTrendDataset,
                PlotOrientation.VERTICAL, true, true, false);
        chart.setBackgroundPaint(java.awt.Color.white);
        chart.setBorderVisible(true);
        chart.setBorderPaint(java.awt.Color.BLACK);
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(java.awt.Color.lightGray);
        plot.setDomainGridlinePaint(java.awt.Color.white);
        plot.setRangeGridlinePaint(java.awt.Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        plot.getRangeAxis().setFixedDimension(15.0);
        return chart;
    }

    private XYDataset createGCTrendDataset(GCLogData data, XYSeriesCollection dataset) {
        String suffix = "";
        if (dataset != null) {
            suffix = "-2";
        }
        XYSeries ygcSeries = new XYSeries("YGC" + suffix);
        Map<String, String> ygcPauseTimes = data.getYGCPauseTimes();
        DecimalFormat timeformat = new DecimalFormat("#0.00");
        DecimalFormat doubleformat = new DecimalFormat("#0.0000");
        for (Entry<String, String> entry : ygcPauseTimes.entrySet()) {
            double happenTime = Double.parseDouble(timeformat.format(Double.parseDouble(entry.getKey())));
            double pauseTime = Double.parseDouble(doubleformat.format(Double.parseDouble(entry.getValue()))) * 1000;
            ygcSeries.add(happenTime, pauseTime, true);
        }
        XYSeries fgcSeries = new XYSeries("FGC" + suffix);
        Map<String, String> fgcPauseTimes = data.getFGCPauseTimes();
        for (Entry<String, String> entry : fgcPauseTimes.entrySet()) {
            double happenTime = Double.parseDouble(timeformat.format(Double.parseDouble(entry.getKey())));
            double pauseTime = Double.parseDouble(doubleformat.format(Double.parseDouble(entry.getValue()))) * 1000;
            fgcSeries.add(happenTime, pauseTime, true);
        }
        XYSeries cmsgcSeries = new XYSeries("CMSGC" + suffix);
        Map<String, String> cmsgcPauseTimes = data.getCMSGCPauseTimes();
        for (Entry<String, String> entry : cmsgcPauseTimes.entrySet()) {
            double happenTime = Double.parseDouble(timeformat.format(Double.parseDouble(entry.getKey())));
            double pauseTime = Double.parseDouble(doubleformat.format(Double.parseDouble(entry.getValue()))) * 1000;
            cmsgcSeries.add(happenTime, pauseTime, true);
        }
        if (dataset == null)
            dataset = new XYSeriesCollection();
        if (fgcPauseTimes.size() > 0)
            dataset.addSeries(fgcSeries);
        if (cmsgcPauseTimes.size() > 0)
            dataset.addSeries(cmsgcSeries);
        dataset.addSeries(ygcSeries);
        return dataset;
    }

    /**
     * create Memory Trend Chart
     */
    private JFreeChart createMemoryTrendChart(GCLogData data) {
        XYDataset memoryTrendDataset = createMemoryTrendDataset(data, null);
        JFreeChart chart = ChartFactory.createXYLineChart("Memory Trend", "Time(S)", "Memory Change(K)",
                memoryTrendDataset, PlotOrientation.VERTICAL, true, true, false);
        chart.setBackgroundPaint(java.awt.Color.white);
        chart.setBorderVisible(true);
        chart.setBorderPaint(java.awt.Color.BLACK);
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(java.awt.Color.lightGray);
        plot.setDomainGridlinePaint(java.awt.Color.white);
        plot.setRangeGridlinePaint(java.awt.Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        plot.getRangeAxis().setFixedDimension(15.0);
        return chart;
    }

    /**
     * create Memory Trend Dataset
     */
    private XYDataset createMemoryTrendDataset(GCLogData data, XYSeriesCollection dataset) {
        String suffix = "";
        if (dataset != null) {
            suffix = "-2";
        }
        XYSeries ygcSeries = new XYSeries("YGC" + suffix);
        Map<String, String[]> ygcMemoryChanges = data.getYGCMemoryChanges();
        DecimalFormat doubleformat = new DecimalFormat("#0.00");
        for (Entry<String, String[]> entry : ygcMemoryChanges.entrySet()) {
            String beginMemoryInfo = entry.getValue()[0];
            String endMemoryInfo = entry.getValue()[1];
            String happenTime = entry.getKey();
            double beginMemory = Double.parseDouble(beginMemoryInfo);
            double endMemory = Double.parseDouble(endMemoryInfo);
            double beginTime = Double.parseDouble(doubleformat.format(Double.parseDouble(happenTime)));
            ygcSeries.add(beginTime, beginMemory, true);
            double pauseTime = Double
                    .parseDouble(doubleformat.format(Double.parseDouble(data.getYGCPauseTimes().get(happenTime))));
            ygcSeries.add(pauseTime + beginTime, endMemory, true);
        }
        XYSeries fgcSeries = new XYSeries("FGC" + suffix);
        Map<String, String[]> fgcMemoryChanges = data.getFGCMemoryChanges();
        for (Entry<String, String[]> entry : fgcMemoryChanges.entrySet()) {
            String beginMemoryInfo = entry.getValue()[0];
            String endMemoryInfo = entry.getValue()[1];
            String happenTime = entry.getKey();
            double beginMemory = Double.parseDouble(beginMemoryInfo);
            double endMemory = Double.parseDouble(endMemoryInfo);
            double beginTime = Double.parseDouble(doubleformat.format(Double.parseDouble(happenTime)));
            fgcSeries.add(beginTime, beginMemory, true);
            double pauseTime = Double
                    .parseDouble(doubleformat.format(Double.parseDouble(data.getFGCPauseTimes().get(happenTime))));
            fgcSeries.add(pauseTime + beginTime, endMemory, true);
        }
        XYSeries cmsgcSeries = new XYSeries("CMSGC" + suffix);
        Map<String, String[]> cmsgcMemoryChanges = data.getCMSGCMemoryChanges();
        for (Entry<String, String[]> entry : cmsgcMemoryChanges.entrySet()) {
            String beginMemoryInfo = entry.getValue()[0];
            String endMemoryInfo = entry.getValue()[1];
            String happenTime = entry.getKey();
            double beginMemory = Double.parseDouble(beginMemoryInfo);
            double endMemory = Double.parseDouble(endMemoryInfo);
            double beginTime = Double.parseDouble(doubleformat.format(Double.parseDouble(happenTime)));
            cmsgcSeries.add(beginTime, beginMemory, true);
            double pauseTime = Double.parseDouble(
                    doubleformat.format(Double.parseDouble(data.getCMSGCPauseTimes().get(happenTime))));
            cmsgcSeries.add(pauseTime + beginTime, endMemory, true);
        }
        if (dataset == null)
            dataset = new XYSeriesCollection();
        if (fgcMemoryChanges.size() > 0) {
            dataset.addSeries(fgcSeries);
        }
        if (cmsgcMemoryChanges.size() > 0) {
            dataset.addSeries(cmsgcSeries);
        }
        dataset.addSeries(ygcSeries);
        return dataset;

    }

    private JFreeChart createLDSTrendChart(GCLogData data) {
        XYDataset ldsTrendDataset = createLDSTrendDataset(data);
        JFreeChart chart = ChartFactory.createXYLineChart("Live Data Size Trend", "Time(S)", "Size(K)",
                ldsTrendDataset, PlotOrientation.VERTICAL, true, true, false);
        chart.setBackgroundPaint(java.awt.Color.white);
        chart.setBorderVisible(true);
        chart.setBorderPaint(java.awt.Color.BLACK);
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(java.awt.Color.lightGray);
        plot.setDomainGridlinePaint(java.awt.Color.white);
        plot.setRangeGridlinePaint(java.awt.Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        plot.getRangeAxis().setFixedDimension(15.0);
        return chart;
    }

    private XYDataset createLDSTrendDataset(GCLogData data) {
        XYSeries ygcSeries = new XYSeries("YGC");
        Map<String, String> ygcLDS = data.getYGCLDS();
        DecimalFormat timeformat = new DecimalFormat("#0.00");
        for (Entry<String, String> entry : ygcLDS.entrySet()) {
            double happenTime = Double.parseDouble(timeformat.format(Double.parseDouble(entry.getKey())));
            double ldsSize = Double.parseDouble(entry.getValue());
            ygcSeries.add(happenTime, ldsSize, true);
        }
        XYSeries fgcSeries = new XYSeries("FGC");
        Map<String, String[]> fgcPauseTimes = data.getFGCMemoryChanges();
        for (Entry<String, String[]> entry : fgcPauseTimes.entrySet()) {
            double happenTime = Double.parseDouble(timeformat.format(Double.parseDouble(entry.getKey())));
            double ldsSize = Double.parseDouble(entry.getValue()[1]);
            fgcSeries.add(happenTime, ldsSize, true);
        }
        XYSeriesCollection dataset = new XYSeriesCollection();
        if (data.getFGC() > 0)
            dataset.addSeries(fgcSeries);
        if (data.getYGC() > 0)
            dataset.addSeries(ygcSeries);
        return dataset;
    }

    private JFreeChart createPTOSTrendChart(GCLogData data) {
        XYDataset ldsTrendDataset = createPTOSTrendDataset(data);
        JFreeChart chart = ChartFactory.createXYLineChart("Promotion To Old Size Trend", "Time(S)", "Size(K)",
                ldsTrendDataset, PlotOrientation.VERTICAL, true, true, false);
        chart.setBackgroundPaint(java.awt.Color.white);
        chart.setBorderVisible(true);
        chart.setBorderPaint(java.awt.Color.BLACK);
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(java.awt.Color.lightGray);
        plot.setDomainGridlinePaint(java.awt.Color.white);
        plot.setRangeGridlinePaint(java.awt.Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        plot.getRangeAxis().setFixedDimension(15.0);
        return chart;
    }

    private XYDataset createPTOSTrendDataset(GCLogData data) {
        XYSeries ygcSeries = new XYSeries("YGC");
        Map<String, String> ygcPTOS = data.getYGCPTOS();
        DecimalFormat timeformat = new DecimalFormat("#0.00");
        for (Entry<String, String> entry : ygcPTOS.entrySet()) {
            double happenTime = Double.parseDouble(timeformat.format(Double.parseDouble(entry.getKey())));
            double ptosSize = Double.parseDouble(entry.getValue());
            ygcSeries.add(happenTime, ptosSize, true);
        }
        XYSeriesCollection dataset = new XYSeriesCollection();
        if (data.getYGC() > 0)
            dataset.addSeries(ygcSeries);
        return dataset;
    }

    class MemoryLeakDetectionListener extends SelectionAdapter {

        @Override
        public void widgetSelected(SelectionEvent e) {
            if (currentGCLogData == null)
                return;
            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    MessageBox messageBox = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
                    messageBox.setText("not realized,u can see if fgc memory changes in growth");
                    messageBox.setMessage(messageBox.getText());
                    messageBox.open();
                }
            });
        }

    }

    class DataForGCTuningListener extends SelectionAdapter {

        @Override
        public void widgetSelected(SelectionEvent e) {
            if (currentGCLogData == null)
                return;
            // change GCTrendChart to LiveDataSizeTrend
            final JFreeChart ldsChart = createLDSTrendChart(currentGCLogData);
            // change MemoryTrendChart to PromotionToOldSizeTrend
            final JFreeChart ptosChart = createPTOSTrendChart(currentGCLogData);
            Display.getDefault().syncExec(new Runnable() {
                public void run() {
                    shell.setText(SHELL_TITLE + ": " + currentGCLogFile + " Data For GC Tuning View");
                    gcTrendChart.setChart(ldsChart);
                    gcTrendChart.pack();
                    gcTrendGroup.layout();
                    memoryTrendChart.setChart(ptosChart);
                    memoryTrendChart.pack();
                    memoryTrendGroup.layout();
                    backToHomeMenuItem.setEnabled(true);
                    avgYGCLDSDataLabel.setText(currentGCLogData.getAVGYGCLDS() + "(K)");
                    avgFGCLDSDataLabel.setText(currentGCLogData.getAVGFGCLDS() + "(K)");
                    avgPTOSDataLabel.setText(currentGCLogData.getAVGPTOS() + "(K)");
                    ((GridData) avgYGCLDSDataLabel.getLayoutData()).exclude = false;
                    summary.layout();
                }
            });
        }

    }

    class BackToHomeListener extends SelectionAdapter {

        @Override
        public void widgetSelected(SelectionEvent e) {
            if (currentGCLogData == null)
                return;
            final JFreeChart gcTrendChartComposite = createGCTrendChart(currentGCLogData);
            final JFreeChart memoryTrendChartComposite = createMemoryTrendChart(currentGCLogData);
            Display.getDefault().syncExec(new Runnable() {
                public void run() {
                    shell.setText(SHELL_TITLE + ": " + currentGCLogFile + " Main View");
                    gcTrendChart.setChart(gcTrendChartComposite);
                    gcTrendChart.pack();
                    gcTrendGroup.layout();
                    memoryTrendChart.setChart(memoryTrendChartComposite);
                    memoryTrendChart.pack();
                    memoryTrendGroup.layout();
                    backToHomeMenuItem.setEnabled(false);
                    ((GridData) avgYGCLDSDataLabel.getLayoutData()).exclude = true;
                    summary.layout();
                }
            });
        }

    }

    class CompareLogListener extends SelectionAdapter {

        @Override
        public void widgetSelected(SelectionEvent e) {
            if (currentGCLogData == null) {
                Display.getDefault().asyncExec(new Runnable() {
                    public void run() {
                        MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK);
                        messageBox.setText("must select one log file first");
                        messageBox.setMessage(messageBox.getText());
                        messageBox.open();
                    }
                });
                return;
            }
            FileDialog dialog = new FileDialog(shell, SWT.OPEN);
            dialog.setFilterNames(FILTER_NAMES);
            dialog.setFilterExtensions(FILTER_EXTS);
            final String fileName = dialog.open();
            if ((fileName != null) && (!"".equals(fileName))) {
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        shell.setText(SHELL_TITLE + ": Compare " + currentGCLogFile + " with " + fileName);
                        ((GridData) bar.getLayoutData()).exclude = false;
                        shell.layout();
                    }
                });
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            final GCLogData data = analyze.analysis(fileName);
                            Display.getDefault().syncExec(new Runnable() {
                                public void run() {
                                    XYSeriesCollection gcTrendDataset = (XYSeriesCollection) gcTrendChart.getChart()
                                            .getXYPlot().getDataset();
                                    createGCTrendDataset(data, gcTrendDataset);
                                    gcTrendChart.pack();
                                    gcTrendGroup.layout();
                                    XYSeriesCollection memoryTrendDataset = (XYSeriesCollection) memoryTrendChart
                                            .getChart().getXYPlot().getDataset();
                                    createMemoryTrendDataset(data, memoryTrendDataset);
                                    memoryTrendChart.pack();
                                    memoryTrendGroup.layout();
                                    backToHomeMenuItem.setEnabled(true);
                                    ((GridData) avgYGCLDSDataLabel.getLayoutData()).exclude = true;
                                    summary.layout();
                                }
                            });
                        } catch (final Exception e) {
                            Display.getDefault().asyncExec(new Runnable() {
                                public void run() {
                                    MessageBox messageBox = new MessageBox(shell, SWT.ERROR | SWT.OK);
                                    messageBox.setText(e.toString());
                                    StringBuilder errorString = new StringBuilder(
                                            "Pls visit GCLogViewer website to feedback this exception,error Details: \r\n");
                                    StackTraceElement[] eles = e.getStackTrace();
                                    for (int i = eles.length - 1; i > eles.length - 5; i--) {
                                        errorString.append(eles[i]);
                                        errorString.append("\r\n");
                                    }
                                    messageBox.setMessage(errorString.toString());
                                    messageBox.open();
                                }
                            });
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }

    }

    class OpenFileListener extends SelectionAdapter {

        private class WatchChartProgress implements ChartProgressListener {
            public void chartProgress(ChartProgressEvent event) {
                switch (event.getType()) {
                case ChartProgressEvent.DRAWING_STARTED:
                    bar.setSelection(bar.getSelection() + 5);
                    break;
                case ChartProgressEvent.DRAWING_FINISHED:
                    bar.setSelection(bar.getSelection() + 30);
                    break;
                default:
                    break;
                }
            }
        }

        public void widgetSelected(SelectionEvent event) {
            FileDialog dialog = new FileDialog(shell, SWT.OPEN);
            dialog.setFilterNames(FILTER_NAMES);
            dialog.setFilterExtensions(FILTER_EXTS);
            final String fileName = dialog.open();
            if ((fileName != null) && (!"".equals(fileName))) {
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        shell.setText(SHELL_TITLE + ": " + fileName + " Main View");
                        ((GridData) bar.getLayoutData()).exclude = false;
                        shell.layout();
                    }
                });
                new Thread(new Runnable() {

                    public void run() {
                        try {
                            final GCLogData data = analyze.analysis(fileName);
                            Display.getDefault().asyncExec(new Runnable() {
                                public void run() {
                                    bar.setSelection(5);
                                }
                            });
                            final JFreeChart chart = createGCTrendChart(data);
                            Display.getDefault().asyncExec(new Runnable() {
                                public void run() {
                                    bar.setSelection(10);
                                }
                            });
                            final JFreeChart chart2 = createMemoryTrendChart(data);
                            Display.getDefault().asyncExec(new Runnable() {
                                public void run() {
                                    bar.setSelection(15);
                                }
                            });
                            chart.addProgressListener(new WatchChartProgress());
                            chart2.addProgressListener(new WatchChartProgress());
                            Display.getDefault().asyncExec(new Runnable() {

                                public void run() {
                                    runtimedataLabel.setText(data.getRuntime());
                                    bar.setSelection(16);
                                    gctypedataLabel.setText(data.getGCType());
                                    bar.setSelection(17);
                                    throughputdataLabel.setText(data.getThroughput());
                                    bar.setSelection(18);
                                    ygcDataLabel.setText(String.valueOf(data.getYGC()));
                                    bar.setSelection(22);
                                    ygctDataLabel.setText(data.getYGCT());
                                    bar.setSelection(23);
                                    avgYGCTDataLabel.setText(data.getAvgYGCT());
                                    bar.setSelection(24);
                                    avgYGCRateDataLabel.setText(data.getAvgYGCRate());
                                    fgcDataLabel.setText(String.valueOf(data.getFGC()));
                                    bar.setSelection(25);
                                    fgctDataLabel.setText(data.getFGCT());
                                    bar.setSelection(26);
                                    avgFGCTDataLabel.setText(data.getAvgFGCT());
                                    avgFGCRateDataLabel.setText(data.getAvgFGCRate());
                                    bar.setSelection(27);
                                    ((GridData) avgYGCLDSDataLabel.getLayoutData()).exclude = true;
                                    compareLogMenuItem.setEnabled(true);
                                    memoryLeakDetectionMenuItem.setEnabled(true);
                                    gcTuningMenuItem.setEnabled(true);
                                    if (data.getCMSGC() > 0) {
                                        cmsgcDataLabel.setText(String.valueOf(data.getCMSGC()));
                                        cmsgctDataLabel.setText(data.getCMSGCT());
                                        avgCMSGCTDataLabel.setText(data.getAvgCMSGCT());
                                        avgCMSGCRateDataLabel.setText(data.getAvgCMSGCRate());
                                        ((GridData) cmsgcDataLabel.getLayoutData()).exclude = false;
                                        summary.layout();
                                    } else {
                                        ((GridData) cmsgcDataLabel.getLayoutData()).exclude = true;
                                        summary.layout();
                                    }
                                    bar.setSelection(30);

                                    if (gcTrendChart == null) {
                                        gcTrendChart = new GCLogChartComposite(gcTrendGroup, SWT.NONE, chart, true);
                                        GridData grid = new GridData(GridData.FILL_BOTH);
                                        gcTrendChart.setLayoutData(grid);
                                    } else {
                                        gcTrendChart.setChart(chart);
                                    }
                                    gcTrendChart.pack();
                                    gcTrendGroup.layout();
                                    if (memoryTrendChart == null) {
                                        memoryTrendChart = new GCLogChartComposite(memoryTrendGroup, SWT.NONE,
                                                chart2, true);
                                        GridData grid = new GridData(GridData.FILL_BOTH);
                                        memoryTrendChart.setLayoutData(grid);
                                    } else {
                                        memoryTrendChart.setChart(chart2);
                                    }
                                    memoryTrendChart.pack();
                                    memoryTrendGroup.layout();
                                }
                            });
                            currentGCLogData = data;
                            currentGCLogFile = fileName;
                        } catch (final Exception e) {
                            Display.getDefault().asyncExec(new Runnable() {
                                public void run() {
                                    MessageBox messageBox = new MessageBox(shell, SWT.ERROR | SWT.OK);
                                    messageBox.setText(e.toString());
                                    StringBuilder errorString = new StringBuilder(
                                            "Pls visit GCLogViewer website to feedback this exception,error Details: \r\n");
                                    StackTraceElement[] eles = e.getStackTrace();
                                    for (int i = eles.length - 1; i > eles.length - 5; i--) {
                                        errorString.append(eles[i]);
                                        errorString.append("\r\n");
                                    }
                                    messageBox.setMessage(errorString.toString());
                                    messageBox.open();
                                }
                            });
                            e.printStackTrace();
                        }
                    }

                }).start();
            }
        }

    }

    class ExitListener extends SelectionAdapter {

        public void widgetSelected(SelectionEvent event) {
            MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK | SWT.CANCEL);
            messageBox.setText("Warning");
            messageBox.setMessage("Are you sure exit?");
            int buttonID = messageBox.open();
            switch (buttonID) {
            case SWT.OK:
                shell.close();
                Display.getDefault().dispose();
            case SWT.CANCEL:
                break;
            }
        }
    }

}