org.uncommons.watchmaker.swing.evolutionmonitor.JVMView Maven / Gradle / Ivy
// ============================================================================
// Copyright 2006-2009 Daniel W. Dyer
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ============================================================================
package org.uncommons.watchmaker.swing.evolutionmonitor;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.TextAnchor;
/**
* Evolution monitor panel that displays information about the current
* state of the Java Virtual machine that is running the program.
* @author Daniel Dyer
*/
class JVMView extends JPanel
{
private static final int MEGABYTE = 1048576;
private final TimeSeries memoryUsageSeries = new TimeSeries("Memory Usage");
private final TimeSeries heapSizeSeries = new TimeSeries("Heap Size");
private final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
JVMView()
{
super(new BorderLayout());
double maxMemory = (double) memoryBean.getHeapMemoryUsage().getMax() / MEGABYTE;
ChartPanel heapPanel = new ChartPanel(createHeapChart(maxMemory),
false, // Properties
true, // Save
true, // Print
false, // Zoom
true); // Tooltips
heapPanel.setMouseZoomable(false);
add(heapPanel, BorderLayout.CENTER);
add(createControls(), BorderLayout.SOUTH);
Timer timer = new Timer(5000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
addMemoryDataPoint();
}
});
// Plot start values.
addMemoryDataPoint();
timer.start();
}
private JFreeChart createHeapChart(double maxMemory)
{
TimeSeriesCollection dataSet = new TimeSeriesCollection();
dataSet.addSeries(memoryUsageSeries);
dataSet.addSeries(heapSizeSeries);
JFreeChart chart = ChartFactory.createXYAreaChart("JVM Heap",
"Time",
"Megabytes",
dataSet,
PlotOrientation.VERTICAL,
true, // Legend.
false, // Tooltips.
false);
DateAxis timeAxis = new DateAxis("Time");
timeAxis.setLowerMargin(0);
timeAxis.setUpperMargin(0);
chart.getXYPlot().setDomainAxis(timeAxis);
chart.getXYPlot().getRangeAxis().setLowerBound(0);
chart.getXYPlot().getRangeAxis().setUpperBound(maxMemory * 1.1); // Add 10% to leave room for marker.
// Add a horizontal marker to indicate the heap growth limit.
ValueMarker marker = new ValueMarker(maxMemory, Color.BLACK, new BasicStroke(1));
marker.setLabel("Maximum Permitted Heap Size (adjust with -Xmx)");
marker.setLabelTextAnchor(TextAnchor.BOTTOM_RIGHT);
marker.setLabelAnchor(RectangleAnchor.RIGHT);
chart.getXYPlot().addRangeMarker(marker);
chart.getXYPlot().getRenderer().setSeriesPaint(0, Color.RED);
chart.getXYPlot().getRenderer().setSeriesPaint(1, new Color(0, 128, 0, 128));
return chart;
}
/**
* Creates the GUI controls for toggling graph display options.
* @return A component that can be added to the main panel.
*/
private JComponent createControls()
{
JPanel controls = new JPanel(new FlowLayout(FlowLayout.RIGHT));
JButton gcButton = new JButton("Request GC");
gcButton.setToolTipText("Perform garbage collection (the JVM may ignore this request).");
gcButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ev)
{
memoryBean.gc();
}
});
controls.add(gcButton);
return controls;
}
private void addMemoryDataPoint()
{
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
double usedMegabytes = (double) heapUsage.getUsed() / MEGABYTE;
Second second = new Second();
memoryUsageSeries.add(second, usedMegabytes);
heapSizeSeries.add(second, (double) heapUsage.getCommitted() / MEGABYTE);
}
}