History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/jconsole/MemoryTab.java (1 of 18352 files). Show all

Unified · Split

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