001: /*
002: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.jconsole;
027:
028: import java.awt.*;
029: import java.awt.event.*;
030: import java.io.*;
031: import java.lang.management.*;
032: import java.lang.reflect.*;
033: import java.util.*;
034: import java.util.concurrent.*;
035:
036: import javax.accessibility.*;
037: import javax.management.*;
038: import javax.management.openmbean.CompositeData;
039: import javax.swing.*;
040: import javax.swing.border.*;
041: import javax.swing.text.*;
042:
043: import sun.management.*;
044:
045: import static sun.tools.jconsole.Formatter.*;
046: import static sun.tools.jconsole.OverviewPanel.*;
047: import static sun.tools.jconsole.Resources.*;
048: import static sun.tools.jconsole.Utilities.*;
049:
050: @SuppressWarnings("serial")
051: class MemoryTab extends Tab implements ActionListener, ItemListener {
052: JComboBox plotterChoice;
053: TimeComboBox timeComboBox;
054: JButton gcButton;
055:
056: PlotterPanel plotterPanel;
057: JPanel bottomPanel;
058: HTMLPane details;
059: PoolChart poolChart;
060:
061: ArrayList<Plotter> plotterList;
062: Plotter heapPlotter, nonHeapPlotter;
063:
064: private MemoryOverviewPanel overviewPanel;
065:
066: private static final String usedKey = "used";
067: private static final String committedKey = "committed";
068: private static final String maxKey = "max";
069: private static final String thresholdKey = "threshold";
070:
071: private static final String usedName = Resources.getText("Used");
072: private static final String committedName = Resources
073: .getText("Committed");
074: private static final String maxName = Resources.getText("Max");
075: private static final String thresholdName = Resources
076: .getText("Threshold");
077:
078: private static final Color usedColor = Plotter.defaultColor;
079: private static final Color committedColor = null;
080: private static final Color maxColor = null;
081: private static final Color thresholdColor = Color.red;
082:
083: private static final String infoLabelFormat = "MemoryTab.infoLabelFormat";
084:
085: /*
086: Hierarchy of panels and layouts for this tab:
087:
088: MemoryTab (BorderLayout)
089:
090: North: topPanel (BorderLayout)
091:
092: Center: controlPanel (FlowLayout)
093: plotterChoice, timeComboBox
094:
095: East: topRightPanel (FlowLayout)
096: gcButton
097:
098: Center: plotterPanel
099:
100: Center: plotter
101:
102: South: bottomPanel (BorderLayout)
103:
104: Center: details
105: East: poolChart
106: */
107:
108: public static String getTabName() {
109: return getText("Memory");
110: }
111:
112: public MemoryTab(VMPanel vmPanel) {
113: super (vmPanel, getTabName());
114:
115: setLayout(new BorderLayout(0, 0));
116: setBorder(new EmptyBorder(4, 4, 3, 4));
117:
118: JPanel topPanel = new JPanel(new BorderLayout());
119: plotterPanel = new PlotterPanel(null);
120: bottomPanel = new JPanel(new BorderLayout());
121:
122: add(topPanel, BorderLayout.NORTH);
123: add(plotterPanel, BorderLayout.CENTER);
124:
125: JPanel controlPanel = new JPanel(new FlowLayout(
126: FlowLayout.LEADING, 20, 5));
127: topPanel.add(controlPanel, BorderLayout.CENTER);
128:
129: // Plotter choice
130: plotterChoice = new JComboBox();
131: plotterChoice.addItemListener(this );
132: controlPanel.add(new LabeledComponent(getText("Chart:"),
133: getMnemonicInt("Chart:"), plotterChoice));
134:
135: // Range control
136: timeComboBox = new TimeComboBox();
137: controlPanel.add(new LabeledComponent(getText("Time Range:"),
138: getMnemonicInt("Time Range:"), timeComboBox));
139:
140: gcButton = new JButton(getText("Perform GC"));
141: gcButton.setMnemonic(getMnemonicInt("Perform GC"));
142: gcButton.addActionListener(this );
143: gcButton.setToolTipText(getText("Perform GC.toolTip"));
144: JPanel topRightPanel = new JPanel();
145: topRightPanel.setBorder(new EmptyBorder(0, 65 - 8, 0, 70));
146: topRightPanel.add(gcButton);
147: topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS);
148:
149: bottomPanel.setBorder(new CompoundBorder(new TitledBorder(
150: getText("Details")), new EmptyBorder(10, 10, 10, 10)));
151:
152: details = new HTMLPane();
153: setAccessibleName(details, getText("Details"));
154: bottomPanel.add(new JScrollPane(details), BorderLayout.CENTER);
155:
156: poolChart = new PoolChart();
157: bottomPanel.add(poolChart, BorderLayout.AFTER_LINE_ENDS);
158: }
159:
160: private void createPlotters() throws IOException {
161: plotterList = new ArrayList<Plotter>();
162:
163: ProxyClient proxyClient = vmPanel.getProxyClient();
164:
165: heapPlotter = new Plotter(Plotter.Unit.BYTES) {
166: public String toString() {
167: return Resources.getText("Heap Memory Usage");
168: }
169: };
170: proxyClient.addWeakPropertyChangeListener(heapPlotter);
171:
172: nonHeapPlotter = new Plotter(Plotter.Unit.BYTES) {
173: public String toString() {
174: return Resources.getText("Non-Heap Memory Usage");
175: }
176: };
177:
178: setAccessibleName(heapPlotter,
179: getText("MemoryTab.heapPlotter.accessibleName"));
180: setAccessibleName(nonHeapPlotter,
181: getText("MemoryTab.nonHeapPlotter.accessibleName"));
182:
183: proxyClient.addWeakPropertyChangeListener(nonHeapPlotter);
184:
185: heapPlotter.createSequence(usedKey, usedName, usedColor, true);
186: heapPlotter.createSequence(committedKey, committedName,
187: committedColor, false);
188: heapPlotter.createSequence(maxKey, maxName, maxColor, false);
189:
190: nonHeapPlotter.createSequence(usedKey, usedName, usedColor,
191: true);
192: nonHeapPlotter.createSequence(committedKey, committedName,
193: committedColor, false);
194: nonHeapPlotter.createSequence(maxKey, maxName, maxColor, false);
195:
196: plotterList.add(heapPlotter);
197: plotterList.add(nonHeapPlotter);
198:
199: // Now add memory pools
200: Map<ObjectName, MBeanInfo> mBeanMap = proxyClient
201: .getMBeans("java.lang");
202: Set<ObjectName> keys = mBeanMap.keySet();
203: ObjectName[] objectNames = keys.toArray(new ObjectName[keys
204: .size()]);
205: ArrayList<PoolPlotter> nonHeapPlotters = new ArrayList<PoolPlotter>(
206: 2);
207: for (ObjectName objectName : objectNames) {
208: String type = objectName.getKeyProperty("type");
209: if (type.equals("MemoryPool")) {
210: String name = getText("MemoryPoolLabel", objectName
211: .getKeyProperty("name"));
212: // Heap or non-heap?
213: boolean isHeap = false;
214: AttributeList al = proxyClient.getAttributes(
215: objectName, new String[] { "Type" });
216: if (al.size() > 0) {
217: isHeap = MemoryType.HEAP.name().equals(
218: ((Attribute) al.get(0)).getValue());
219: }
220: PoolPlotter poolPlotter = new PoolPlotter(objectName,
221: name, isHeap);
222: proxyClient.addWeakPropertyChangeListener(poolPlotter);
223:
224: poolPlotter.createSequence(usedKey, usedName,
225: usedColor, true);
226: poolPlotter.createSequence(committedKey, committedName,
227: committedColor, false);
228: poolPlotter.createSequence(maxKey, maxName, maxColor,
229: false);
230: poolPlotter.createSequence(thresholdKey, thresholdName,
231: thresholdColor, false);
232: poolPlotter.setUseDashedTransitions(thresholdKey, true);
233:
234: if (isHeap) {
235: plotterList.add(poolPlotter);
236: } else {
237: // Will be added to plotterList below
238: nonHeapPlotters.add(poolPlotter);
239: }
240: }
241: }
242: // Add non-heap plotters last
243: for (PoolPlotter poolPlotter : nonHeapPlotters) {
244: plotterList.add(poolPlotter);
245: }
246: }
247:
248: public void itemStateChanged(ItemEvent ev) {
249: if (ev.getStateChange() == ItemEvent.SELECTED) {
250: Plotter plotter = (Plotter) plotterChoice.getSelectedItem();
251: plotterPanel.setPlotter(plotter);
252: }
253: }
254:
255: public void gc() {
256: new Thread("MemoryPanel.gc") {
257: public void run() {
258: ProxyClient proxyClient = vmPanel.getProxyClient();
259: try {
260: proxyClient.getMemoryMXBean().gc();
261: } catch (UndeclaredThrowableException e) {
262: proxyClient.markAsDead();
263: } catch (IOException e) {
264: // Ignore
265: }
266: }
267: }.start();
268: }
269:
270: public SwingWorker<?, ?> newSwingWorker() {
271: return new SwingWorker<Boolean, Object>() {
272: private long[] used, committed, max, threshold;
273: private long timeStamp;
274: private String detailsStr;
275: private boolean initialRun = false;
276:
277: public Boolean doInBackground() {
278: ProxyClient proxyClient = vmPanel.getProxyClient();
279:
280: if (plotterList == null) {
281: try {
282: createPlotters();
283: } catch (UndeclaredThrowableException e) {
284: proxyClient.markAsDead();
285: return false;
286: } catch (final IOException ex) {
287: return false;
288: }
289: initialRun = true;
290: }
291:
292: int n = plotterList.size();
293: used = new long[n];
294: committed = new long[n];
295: max = new long[n];
296: threshold = new long[n];
297: timeStamp = System.currentTimeMillis();
298: int poolCount = 0;
299:
300: for (int i = 0; i < n; i++) {
301: Plotter plotter = plotterList.get(i);
302: MemoryUsage mu = null;
303: used[i] = -1L;
304: threshold[i] = -1L;
305:
306: try {
307: if (plotter instanceof PoolPlotter) {
308: PoolPlotter poolPlotter = (PoolPlotter) plotter;
309: ObjectName objectName = poolPlotter.objectName;
310: AttributeList al = proxyClient
311: .getAttributes(objectName,
312: new String[] { "Usage",
313: "UsageThreshold" });
314: if (al.size() > 0) {
315: CompositeData cd = (CompositeData) ((Attribute) al
316: .get(0)).getValue();
317: mu = MemoryUsage.from(cd);
318:
319: if (al.size() > 1) {
320: threshold[i] = (Long) ((Attribute) al
321: .get(1)).getValue();
322: }
323: }
324: } else if (plotter == heapPlotter) {
325: mu = proxyClient.getMemoryMXBean()
326: .getHeapMemoryUsage();
327: } else if (plotter == nonHeapPlotter) {
328: mu = proxyClient.getMemoryMXBean()
329: .getNonHeapMemoryUsage();
330: }
331: } catch (UndeclaredThrowableException e) {
332: proxyClient.markAsDead();
333: return false;
334: } catch (IOException ex) {
335: // Skip this plotter
336: }
337:
338: if (mu != null) {
339: used[i] = mu.getUsed();
340: committed[i] = mu.getCommitted();
341: max[i] = mu.getMax();
342: }
343: }
344: detailsStr = formatDetails();
345:
346: return true;
347: }
348:
349: protected void done() {
350: try {
351: if (!get()) {
352: return;
353: }
354: } catch (InterruptedException ex) {
355: return;
356: } catch (ExecutionException ex) {
357: if (JConsole.isDebug()) {
358: ex.printStackTrace();
359: }
360: return;
361: }
362:
363: if (initialRun) {
364: // Add Memory Pools
365: for (Plotter p : plotterList) {
366: plotterChoice.addItem(p);
367: timeComboBox.addPlotter(p);
368: }
369: add(bottomPanel, BorderLayout.SOUTH);
370: }
371:
372: int n = plotterList.size();
373: int poolCount = 0;
374:
375: for (int i = 0; i < n; i++) {
376: Plotter plotter = plotterList.get(i);
377: if (used[i] >= 0L) {
378: if (plotter instanceof PoolPlotter) {
379: plotter.addValues(timeStamp, used[i],
380: committed[i], max[i], threshold[i]);
381: if (threshold[i] > 0L) {
382: plotter
383: .setIsPlotted(thresholdKey,
384: true);
385: }
386: poolChart.setValue(poolCount++,
387: (PoolPlotter) plotter, used[i],
388: threshold[i], max[i]);
389: } else {
390: plotter.addValues(timeStamp, used[i],
391: committed[i], max[i]);
392: }
393:
394: if (plotter == heapPlotter
395: && overviewPanel != null) {
396: overviewPanel.getPlotter().addValues(
397: timeStamp, used[i]);
398: overviewPanel.updateMemoryInfo(used[i],
399: committed[i], max[i]);
400: }
401: }
402: }
403: details.setText(detailsStr);
404: }
405: };
406: }
407:
408: private String formatDetails() {
409: ProxyClient proxyClient = vmPanel.getProxyClient();
410: if (proxyClient.isDead()) {
411: return "";
412: }
413:
414: String text = "<table cellspacing=0 cellpadding=0>";
415:
416: Plotter plotter = (Plotter) plotterChoice.getSelectedItem();
417: if (plotter == null) {
418: return "";
419: }
420:
421: //long time = plotter.getLastTimeStamp();
422: long time = System.currentTimeMillis();
423: String timeStamp = formatDateTime(time);
424: text += newRow(getText("Time"), timeStamp);
425:
426: long used = plotter.getLastValue(usedKey);
427: long committed = plotter.getLastValue(committedKey);
428: long max = plotter.getLastValue(maxKey);
429: long threshold = plotter.getLastValue(thresholdKey);
430:
431: text += newRow(getText("Used"), formatKBytes(used));
432: if (committed > 0L) {
433: text += newRow(getText("Committed"),
434: formatKBytes(committed));
435: }
436: if (max > 0L) {
437: text += newRow(getText("Max"), formatKBytes(max));
438: }
439: if (threshold > 0L) {
440: text += newRow(getText("Usage Threshold"),
441: formatKBytes(threshold));
442: }
443:
444: try {
445: Collection<GarbageCollectorMXBean> garbageCollectors = proxyClient
446: .getGarbageCollectorMXBeans();
447:
448: boolean descPrinted = false;
449: for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
450: String gcName = garbageCollectorMBean.getName();
451: long gcCount = garbageCollectorMBean
452: .getCollectionCount();
453: long gcTime = garbageCollectorMBean.getCollectionTime();
454: String str = getText("GC time details", justify(
455: formatTime(gcTime), 14), gcName, String.format(
456: "%,d", gcCount));
457: if (!descPrinted) {
458: text += newRow(getText("GC time"), str);
459: descPrinted = true;
460: } else {
461: text += newRow(null, str);
462: }
463: }
464: } catch (IOException e) {
465: }
466:
467: return text;
468: }
469:
470: public void actionPerformed(ActionEvent ev) {
471: Object src = ev.getSource();
472: if (src == gcButton) {
473: gc();
474: }
475: }
476:
477: private class PoolPlotter extends Plotter {
478: ObjectName objectName;
479: String name;
480: boolean isHeap;
481: long value, threshold, max;
482: int barX;
483:
484: public PoolPlotter(ObjectName objectName, String name,
485: boolean isHeap) {
486: super (Plotter.Unit.BYTES);
487:
488: this .objectName = objectName;
489: this .name = name;
490: this .isHeap = isHeap;
491:
492: setAccessibleName(this , getText(
493: "MemoryTab.poolPlotter.accessibleName", name));
494: }
495:
496: public String toString() {
497: return name;
498: }
499: }
500:
501: private class PoolChart extends BorderedComponent implements
502: Accessible, MouseListener {
503: final int height = 150;
504: final int leftMargin = 50;
505: final int rightMargin = 23;
506: final int bottomMargin = 35;
507: final int barWidth = 22;
508: final int barGap = 3;
509: final int groupGap = 8;
510: final int barHeight = height * 2 / 3;
511:
512: final Color greenBar = new Color(100, 255, 100);
513: final Color greenBarBackground = new Color(210, 255, 210);
514: final Color redBarBackground = new Color(255, 210, 210);
515:
516: Font smallFont = null;
517:
518: ArrayList<PoolPlotter> poolPlotters = new ArrayList<PoolPlotter>(
519: 5);
520:
521: int nHeapPools = 0;
522: int nNonHeapPools = 0;
523: Rectangle heapRect = new Rectangle(leftMargin, height
524: - bottomMargin + 6, barWidth, 20);
525: Rectangle nonHeapRect = new Rectangle(leftMargin + groupGap,
526: height - bottomMargin + 6, barWidth, 20);
527:
528: public PoolChart() {
529: super (null, null);
530:
531: setFocusable(true);
532: addMouseListener(this );
533: ToolTipManager.sharedInstance().registerComponent(this );
534: }
535:
536: public void setValue(int poolIndex, PoolPlotter poolPlotter,
537: long value, long threshold, long max) {
538: poolPlotter.value = value;
539: poolPlotter.threshold = threshold;
540: poolPlotter.max = max;
541:
542: if (poolIndex == poolPlotters.size()) {
543: poolPlotters.add(poolPlotter);
544: if (poolPlotter.isHeap) {
545: poolPlotter.barX = nHeapPools * (barWidth + barGap);
546: nHeapPools++;
547: heapRect.width = nHeapPools * barWidth
548: + (nHeapPools - 1) * barGap;
549: nonHeapRect.x = leftMargin + heapRect.width
550: + groupGap;
551: } else {
552: poolPlotter.barX = nonHeapRect.x - leftMargin
553: + nNonHeapPools * (barWidth + barGap);
554: nNonHeapPools++;
555: nonHeapRect.width = nNonHeapPools * barWidth
556: + (nNonHeapPools - 1) * barGap;
557: }
558: } else {
559: poolPlotters.set(poolIndex, poolPlotter);
560: }
561: repaint();
562: }
563:
564: private void paintPoolBar(Graphics g, PoolPlotter poolPlotter) {
565: Rectangle barRect = getBarRect(poolPlotter);
566: g.setColor(Color.gray);
567: g.drawRect(barRect.x, barRect.y, barRect.width,
568: barRect.height);
569:
570: long value = poolPlotter.value;
571: long max = poolPlotter.max;
572: if (max > 0L) {
573: g.translate(barRect.x, barRect.y);
574:
575: // Paint green background
576: g.setColor(greenBarBackground);
577: g.fillRect(1, 1, barRect.width - 1, barRect.height - 1);
578:
579: int greenHeight = (int) (value * barRect.height / max);
580: long threshold = poolPlotter.threshold;
581: if (threshold > 0L) {
582: int redHeight = (int) (threshold * barRect.height / max);
583:
584: // Paint red background
585: g.setColor(redBarBackground);
586: g.fillRect(1, 1, barRect.width - 1, barRect.height
587: - redHeight);
588:
589: if (value > threshold) {
590: // Over threshold, paint red bar
591: g.setColor(thresholdColor);
592: g.fillRect(1, barRect.height - greenHeight,
593: barRect.width - 1, greenHeight
594: - redHeight);
595: greenHeight = redHeight;
596: }
597: }
598:
599: // Paint green bar
600: g.setColor(greenBar);
601: g.fillRect(1, barRect.height - greenHeight,
602: barRect.width - 1, greenHeight);
603:
604: g.translate(-barRect.x, -barRect.y);
605: }
606: }
607:
608: public void paintComponent(Graphics g) {
609: super .paintComponent(g);
610:
611: if (poolPlotters.size() == 0) {
612: return;
613: }
614:
615: if (smallFont == null) {
616: smallFont = g.getFont().deriveFont(9.0F);
617: }
618:
619: // Paint background for chart area
620: g.setColor(getBackground());
621: Rectangle r = g.getClipBounds();
622: g.fillRect(r.x, r.y, r.width, r.height);
623:
624: g.setFont(smallFont);
625: FontMetrics fm = g.getFontMetrics();
626: int fontDescent = fm.getDescent();
627:
628: // Paint percentage axis
629: g.setColor(getForeground());
630: for (int pc : new int[] { 0, 25, 50, 75, 100 }) {
631: String str = pc + "% --";
632: g.drawString(str, leftMargin - fm.stringWidth(str) - 4,
633: height - bottomMargin - (pc * barHeight / 100)
634: + fontDescent + 1);
635: }
636:
637: for (PoolPlotter poolPlotter : poolPlotters) {
638: paintPoolBar(g, poolPlotter);
639: }
640:
641: g.setColor(Color.gray);
642: g.drawRect(heapRect.x, heapRect.y, heapRect.width,
643: heapRect.height);
644: g.drawRect(nonHeapRect.x, nonHeapRect.y, nonHeapRect.width,
645: nonHeapRect.height);
646:
647: Color heapColor = greenBar;
648: Color nonHeapColor = greenBar;
649:
650: for (PoolPlotter poolPlotter : poolPlotters) {
651: if (poolPlotter.threshold > 0L
652: && poolPlotter.value > poolPlotter.threshold) {
653: if (poolPlotter.isHeap) {
654: heapColor = thresholdColor;
655: } else {
656: nonHeapColor = thresholdColor;
657: }
658: }
659: }
660: g.setColor(heapColor);
661: g.fillRect(heapRect.x + 1, heapRect.y + 1,
662: heapRect.width - 1, heapRect.height - 1);
663: g.setColor(nonHeapColor);
664: g.fillRect(nonHeapRect.x + 1, nonHeapRect.y + 1,
665: nonHeapRect.width - 1, nonHeapRect.height - 1);
666:
667: String str = getText("Heap");
668: int stringWidth = fm.stringWidth(str);
669: int x = heapRect.x + (heapRect.width - stringWidth) / 2;
670: int y = heapRect.y + heapRect.height - 6;
671: g.setColor(Color.white);
672: g.drawString(str, x - 1, y - 1);
673: g.drawString(str, x + 1, y - 1);
674: g.drawString(str, x - 1, y + 1);
675: g.drawString(str, x + 1, y + 1);
676: g.setColor(Color.black);
677: g.drawString(str, x, y);
678:
679: str = getText("Non-Heap");
680: stringWidth = fm.stringWidth(str);
681: x = nonHeapRect.x + (nonHeapRect.width - stringWidth) / 2;
682: y = nonHeapRect.y + nonHeapRect.height - 6;
683: g.setColor(Color.white);
684: g.drawString(str, x - 1, y - 1);
685: g.drawString(str, x + 1, y - 1);
686: g.drawString(str, x - 1, y + 1);
687: g.drawString(str, x + 1, y + 1);
688: g.setColor(Color.black);
689: g.drawString(str, x, y);
690:
691: // Highlight current plotter
692: g.setColor(Color.blue);
693: r = null;
694: Plotter plotter = (Plotter) plotterChoice.getSelectedItem();
695: if (plotter == heapPlotter) {
696: r = heapRect;
697: } else if (plotter == nonHeapPlotter) {
698: r = nonHeapRect;
699: } else if (plotter instanceof PoolPlotter) {
700: r = getBarRect((PoolPlotter) plotter);
701: }
702: if (r != null) {
703: g.drawRect(r.x - 1, r.y - 1, r.width + 2, r.height + 2);
704: }
705: }
706:
707: private Rectangle getBarRect(PoolPlotter poolPlotter) {
708: return new Rectangle(leftMargin + poolPlotter.barX, height
709: - bottomMargin - barHeight, barWidth, barHeight);
710: }
711:
712: public Dimension getPreferredSize() {
713: return new Dimension(nonHeapRect.x + nonHeapRect.width
714: + rightMargin, height);
715: }
716:
717: public void mouseClicked(MouseEvent e) {
718: requestFocusInWindow();
719: Plotter plotter = getPlotter(e);
720:
721: if (plotter != null
722: && plotter != plotterChoice.getSelectedItem()) {
723: plotterChoice.setSelectedItem(plotter);
724: repaint();
725: }
726: }
727:
728: public String getToolTipText(MouseEvent e) {
729: Plotter plotter = getPlotter(e);
730:
731: return (plotter != null) ? plotter.toString() : null;
732: }
733:
734: private Plotter getPlotter(MouseEvent e) {
735: Point p = e.getPoint();
736: Plotter plotter = null;
737:
738: if (heapRect.contains(p)) {
739: plotter = heapPlotter;
740: } else if (nonHeapRect.contains(p)) {
741: plotter = nonHeapPlotter;
742: } else {
743: for (PoolPlotter poolPlotter : poolPlotters) {
744: if (getBarRect(poolPlotter).contains(p)) {
745: plotter = poolPlotter;
746: break;
747: }
748: }
749: }
750: return plotter;
751: }
752:
753: public void mousePressed(MouseEvent e) {
754: }
755:
756: public void mouseReleased(MouseEvent e) {
757: }
758:
759: public void mouseEntered(MouseEvent e) {
760: }
761:
762: public void mouseExited(MouseEvent e) {
763: }
764:
765: public AccessibleContext getAccessibleContext() {
766: if (accessibleContext == null) {
767: accessibleContext = new AccessiblePoolChart();
768: }
769: return accessibleContext;
770: }
771:
772: protected class AccessiblePoolChart extends AccessibleJPanel {
773: public String getAccessibleName() {
774: String name = getText("MemoryTab.poolChart.accessibleName");
775:
776: String keyValueList = "";
777: for (PoolPlotter poolPlotter : poolPlotters) {
778: String value = (poolPlotter.value * 100 / poolPlotter.max)
779: + "%";
780: // Assume format string ends with newline
781: keyValueList += getText(
782: "Plotter.accessibleName.keyAndValue",
783: poolPlotter.toString(), value);
784: if (poolPlotter.threshold > 0L) {
785: String threshold = (poolPlotter.threshold * 100 / poolPlotter.max)
786: + "%";
787: if (poolPlotter.value > poolPlotter.threshold) {
788: keyValueList += getText(
789: "MemoryTab.poolChart.aboveThreshold",
790: threshold);
791: } else {
792: keyValueList += getText(
793: "MemoryTab.poolChart.belowThreshold",
794: threshold);
795: }
796: }
797: }
798:
799: return name + "\n" + keyValueList + ".";
800: }
801: }
802: }
803:
804: OverviewPanel[] getOverviewPanels() {
805: if (overviewPanel == null) {
806: overviewPanel = new MemoryOverviewPanel();
807: }
808: return new OverviewPanel[] { overviewPanel };
809: }
810:
811: private static class MemoryOverviewPanel extends OverviewPanel {
812: MemoryOverviewPanel() {
813: super (getText("Heap Memory Usage"), usedKey, usedName,
814: Plotter.Unit.BYTES);
815: }
816:
817: private void updateMemoryInfo(long used, long committed,
818: long max) {
819: getInfoLabel().setText(
820: getText(infoLabelFormat, formatBytes(used, true),
821: formatBytes(committed, true), formatBytes(
822: max, true)));
823: }
824: }
825: }
|