• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package ohos.devtools.views.layout.chartview.memory;
17 
18 import com.intellij.icons.AllIcons;
19 import com.intellij.openapi.util.IconLoader;
20 import com.intellij.ui.JBColor;
21 import com.intellij.ui.JBSplitter;
22 import com.intellij.ui.components.JBLabel;
23 import com.intellij.ui.components.JBPanel;
24 import com.intellij.ui.components.JBScrollPane;
25 import com.intellij.ui.table.JBTable;
26 import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
27 import net.miginfocom.swing.MigLayout;
28 import ohos.devtools.datasources.utils.common.Constant;
29 import ohos.devtools.datasources.utils.device.entity.DeviceIPPortInfo;
30 import ohos.devtools.datasources.utils.device.entity.DeviceType;
31 import ohos.devtools.datasources.utils.process.entity.ProcessInfo;
32 import ohos.devtools.datasources.utils.process.service.ProcessManager;
33 import ohos.devtools.datasources.utils.profilerlog.ProfilerLogManager;
34 import ohos.devtools.datasources.utils.session.entity.SessionInfo;
35 import ohos.devtools.datasources.utils.session.service.SessionManager;
36 import ohos.devtools.services.memory.agentbean.AgentHeapBean;
37 import ohos.devtools.services.memory.agentbean.MemoryInstanceDetailsInfo;
38 import ohos.devtools.services.memory.agentbean.MemoryInstanceInfo;
39 import ohos.devtools.services.memory.agentdao.MemoryInstanceDetailsManager;
40 import ohos.devtools.services.memory.agentdao.MemoryInstanceManager;
41 import ohos.devtools.views.charts.FilledLineChart;
42 import ohos.devtools.views.charts.ProfilerChart;
43 import ohos.devtools.views.charts.model.ChartDataModel;
44 import ohos.devtools.views.charts.model.ChartDataRange;
45 import ohos.devtools.views.charts.model.ChartLegendColorRect;
46 import ohos.devtools.views.charts.model.ChartStandard;
47 import ohos.devtools.views.charts.tooltip.TooltipItem;
48 import ohos.devtools.views.common.LayoutConstants;
49 import ohos.devtools.views.common.UtConstant;
50 import ohos.devtools.views.common.customcomp.DottedLine;
51 import ohos.devtools.views.common.treetable.ExpandTreeTable;
52 import ohos.devtools.views.layout.chartview.ItemsView;
53 import ohos.devtools.views.layout.chartview.MonitorItemDetail;
54 import ohos.devtools.views.layout.chartview.MonitorItemView;
55 import ohos.devtools.views.layout.chartview.ProfilerChartsView;
56 import ohos.devtools.views.layout.chartview.ProfilerMonitorItem;
57 import ohos.devtools.views.layout.chartview.cpu.CpuItemView;
58 import ohos.devtools.views.layout.chartview.memory.javaagent.AgentTreeTableRowSorter;
59 import ohos.devtools.views.layout.chartview.memory.javaagent.MemoryAgentHeapInfoPanel;
60 import ohos.devtools.views.layout.chartview.memory.javaagent.MemoryTreeTablePanel;
61 import ohos.devtools.views.layout.chartview.memory.nativehook.NativeConfigDialog;
62 import ohos.devtools.views.layout.chartview.observer.MemoryChartObserver;
63 import ohos.devtools.views.layout.dialog.CustomDialog;
64 import ohos.devtools.views.layout.dialog.NativeRecordDialog;
65 import ohos.devtools.views.layout.utils.EventTrackUtils;
66 import org.apache.logging.log4j.LogManager;
67 import org.apache.logging.log4j.Logger;
68 
69 import javax.swing.BorderFactory;
70 import javax.swing.BoundedRangeModel;
71 import javax.swing.Icon;
72 import javax.swing.JButton;
73 import javax.swing.JComponent;
74 import javax.swing.JLabel;
75 import javax.swing.JPanel;
76 import javax.swing.JScrollBar;
77 import javax.swing.JTable;
78 import javax.swing.RowSorter;
79 import javax.swing.SortOrder;
80 import javax.swing.SwingUtilities;
81 import javax.swing.SwingWorker;
82 import javax.swing.table.DefaultTableCellRenderer;
83 import javax.swing.table.DefaultTableModel;
84 import javax.swing.table.TableModel;
85 import javax.swing.table.TableRowSorter;
86 import javax.swing.tree.DefaultMutableTreeNode;
87 import java.awt.BorderLayout;
88 import java.awt.Color;
89 import java.awt.Component;
90 import java.awt.Dimension;
91 import java.awt.FlowLayout;
92 import java.awt.Font;
93 import java.awt.event.ComponentAdapter;
94 import java.awt.event.ComponentEvent;
95 import java.awt.event.MouseAdapter;
96 import java.awt.event.MouseEvent;
97 import java.awt.event.MouseMotionAdapter;
98 import java.io.PrintWriter;
99 import java.io.StringWriter;
100 import java.math.BigDecimal;
101 import java.util.ArrayList;
102 import java.util.Arrays;
103 import java.util.Date;
104 import java.util.HashMap;
105 import java.util.LinkedHashMap;
106 import java.util.List;
107 import java.util.Locale;
108 import java.util.Map;
109 import java.util.Objects;
110 import java.util.Vector;
111 import java.util.concurrent.TimeUnit;
112 
113 import static ohos.devtools.pluginconfig.NativeConfig.NATIVE_HOOK_PLUGIN_NAME;
114 import static ohos.devtools.views.charts.utils.ChartUtils.divide;
115 import static ohos.devtools.views.layout.chartview.MonitorItemDetail.MEM_CODE;
116 import static ohos.devtools.views.layout.chartview.MonitorItemDetail.MEM_GRAPHICS;
117 import static ohos.devtools.views.layout.chartview.MonitorItemDetail.MEM_JAVA;
118 import static ohos.devtools.views.layout.chartview.MonitorItemDetail.MEM_NATIVE;
119 import static ohos.devtools.views.layout.chartview.MonitorItemDetail.MEM_OTHERS;
120 import static ohos.devtools.views.layout.chartview.MonitorItemDetail.MEM_STACK;
121 import static ohos.devtools.views.layout.chartview.utils.ChartViewConstants.NUM_1024;
122 
123 /**
124  * Memory monitor item view
125  *
126  * @since : 2021/10/25
127  */
128 public class MemoryItemView extends MonitorItemView {
129     /**
130      * memory tootle Legend color
131      */
132     public static final Color MEMORY_FIRST_PANEL_COLOR = new JBColor(new Color(65, 155, 249), new Color(65, 155, 249));
133 
134     private static final Logger LOGGER = LogManager.getLogger(MemoryItemView.class);
135 
136     /**
137      * Splitter PROPORTION
138      */
139     private static final float PROPORTION_SEGMENT_HEAP = 0.5f;
140 
141     /**
142      * instance title width
143      */
144     private static final int INSTANCE_TITLE_WIDTH = 630;
145 
146     /**
147      * instance title height
148      */
149     private static final int INSTANCE_TITLE_HEIGHT = 34;
150 
151     /**
152      * instance pane height
153      */
154     private static final int INSTANCE_PANE_HEIGHT = 450;
155 
156     /**
157      * instance jScrollPane height
158      */
159     private static final int INSTANCE_SCROLL_HEIGHT = 425;
160 
161     /**
162      * instance view width
163      */
164     private static final float PROPORTION_SEGMENT_VIEW = 0.4f;
165 
166     /**
167      * instance view width
168      */
169     private static final int HEAP_VIEW_PANEL_WIDTH = 410;
170 
171     private static final int NUM_418 = 418;
172 
173     private static final int NUM_384 = 384;
174 
175     private static final int NUM_2 = 2;
176 
177     /**
178      * KB,MB转换时的单位
179      */
180     private static final int UNIT = 1024;
181 
182     /**
183      * instanceViewTable
184      */
185     public JBTable instanceViewTable;
186 
187     /**
188      * agentHeapSplitter
189      */
190     public JBSplitter agentHeapSplitter = new JBSplitter(false, PROPORTION_SEGMENT_HEAP);
191 
192     /**
193      * instanceAndDetailSplitter
194      */
195     public JBSplitter instanceAndDetailSplitter = new JBSplitter(false, PROPORTION_SEGMENT_HEAP);
196     private final JBLabel totalLabel = new JBLabel();
197     private final ChartLegendColorRect totalColor = new ChartLegendColorRect();
198     private final JBLabel javaLabel = new JBLabel();
199     private final ChartLegendColorRect javaColor = new ChartLegendColorRect();
200     private final JBLabel nativeLabel = new JBLabel();
201     private final ChartLegendColorRect nativeColor = new ChartLegendColorRect();
202     private final JBLabel graphicsLabel = new JBLabel();
203     private final ChartLegendColorRect graphicsColor = new ChartLegendColorRect();
204     private final JBLabel stackLabel = new JBLabel();
205     private final ChartLegendColorRect stackColor = new ChartLegendColorRect();
206     private final JBLabel codeLabel = new JBLabel();
207     private final ChartLegendColorRect codeColor = new ChartLegendColorRect();
208     private final JBLabel othersLabel = new JBLabel();
209     private final ChartLegendColorRect othersColor = new ChartLegendColorRect();
210     private MemoryChartObserver chartObserver;
211     private JBPanel heapViewPanel;
212     private MemoryTreeTablePanel memoryTreeTablePanel;
213     private JBLabel foldBtn;
214     private JBLabel heapDumpBtn;
215     private JBLabel detailCfgBtn;
216     private JButton nativeBtn;
217     private ProfilerMonitorItem item;
218 
219     /**
220      * Constructor
221      */
MemoryItemView()222     public MemoryItemView() {
223         if (ProfilerLogManager.isInfoEnabled()) {
224             LOGGER.info("create MemoryItemView");
225         }
226     }
227 
228     @Override
init(ProfilerChartsView bottomPanel, ItemsView parent, ProfilerMonitorItem item)229     public void init(ProfilerChartsView bottomPanel, ItemsView parent, ProfilerMonitorItem item) {
230         this.setName(UtConstant.UT_MEMORY_ITEM_VIEW);
231         this.bottomPanel = bottomPanel;
232         this.parent = parent;
233         this.item = item;
234         this.setLayout(new BorderLayout());
235         initLegendsComp();
236         addChart();
237         MemoryTitleView titleView = new MemoryTitleView();
238         this.add(titleView, BorderLayout.NORTH);
239         this.addComponentListener(new ComponentAdapter() {
240             @Override
241             public void componentResized(ComponentEvent event) {
242                 int height = bottomPanel.getHeight() / 5 * 3;
243                 if (heapViewPanel != null) {
244                     chart.setPreferredSize(new Dimension(bottomPanel.getWidth(), height));
245                     repaint();
246                 }
247             }
248         });
249     }
250 
initLegendsComp()251     private void initLegendsComp() {
252         if (ProfilerLogManager.isInfoEnabled()) {
253             LOGGER.info("initLegendsComp");
254         }
255         totalLabel.setOpaque(false);
256         javaLabel.setOpaque(false);
257         nativeLabel.setOpaque(false);
258         graphicsLabel.setOpaque(false);
259         stackLabel.setOpaque(false);
260         codeLabel.setOpaque(false);
261         othersLabel.setOpaque(false);
262         addDivideMouseListener(agentHeapSplitter);
263         addDivideMouseListener(instanceAndDetailSplitter);
264     }
265 
266     /**
267      * Splitter Divide add MouseListener
268      *
269      * @param splitter jbSplitter
270      */
addDivideMouseListener(JBSplitter splitter)271     private void addDivideMouseListener(JBSplitter splitter) {
272         splitter.getDivider().addMouseListener(new MouseAdapter() {
273             @Override
274             public void mouseEntered(MouseEvent event) {
275                 bottomPanel.getTaskScenePanelChart().getSplitPane().setEnabled(true);
276             }
277 
278             @Override
279             public void mouseExited(MouseEvent event) {
280                 bottomPanel.getTaskScenePanelChart().getSplitPane().setEnabled(false);
281             }
282         });
283     }
284 
285     /**
286      * Add chart panel
287      */
addChart()288     private void addChart() {
289         if (ProfilerLogManager.isInfoEnabled()) {
290             LOGGER.info("addChart");
291         }
292         chart = generateChart();
293         // Register the chart observer to the ProfilerChartsView and listen to the refresh events of the main interface
294         chartObserver = new MemoryChartObserver(chart, bottomPanel.getSessionId(), true);
295         this.bottomPanel.getPublisher().attach(chartObserver);
296         this.add(chart, BorderLayout.CENTER);
297     }
298 
generateChart()299     private ProfilerChart generateChart() {
300         ProfilerChart memoryChart = new FilledLineChart(this.bottomPanel, item.getName(), true) {
301             @Override
302             protected void initLegends() {
303                 MemoryItemView.this.initChartLegends(legends);
304             }
305 
306             @Override
307             protected String getYaxisLabelStr(int value) {
308                 // Here we get KB, we need to convert it to MB
309                 return value == maxUnitY ? divide(value, UNIT) + " " + axisLabelY : divide(value, UNIT) + "";
310             }
311 
312             @Override
313             protected void buildLegends(List<ChartDataModel> lastModels) {
314                 MemoryItemView.this.buildChartLegends(lastModels);
315             }
316 
317             @Override
318             protected void buildTooltip(int showKey, int actualKey, boolean newChart) {
319                 String totalValue = calcTotal(actualKey, dataMap);
320                 List<TooltipItem> tooltipItems = buildTooltipItems(actualKey, dataMap);
321                 tooltip.showTip(this, showKey + "", totalValue, tooltipItems, newChart, axisLabelY);
322             }
323 
324             @Override
325             protected void leftMouseClickEvent(MouseEvent event) {
326                 MemoryItemView.this.chartLeftMouseClick();
327             }
328 
329             @Override
330             protected void rightMouseClickEvent(MouseEvent event) {
331                 MemoryItemView.this.chartRightMouseClick();
332             }
333 
334             @Override
335             protected void mouseDraggedEvent(MouseEvent event) {
336                 MemoryItemView.this.chartMouseDragged();
337             }
338 
339             @Override
340             protected void mouseReleaseEvent(MouseEvent event) {
341                 MemoryItemView.this.chartMouseRelease();
342             }
343         };
344         memoryChart.setMaxDisplayX(this.bottomPanel.getPublisher().getStandard().getMaxDisplayMillis());
345         memoryChart.setMinMarkIntervalX(this.bottomPanel.getPublisher().getStandard().getMinMarkInterval());
346         memoryChart.setSectionNumY(NUM_2);
347         memoryChart.setAxisLabelY("MB");
348         memoryChart.setFold(true);
349         memoryChart.setEnableSelect(false);
350         return memoryChart;
351     }
352 
353     /**
354      * Init legend components of chart
355      *
356      * @param legends legends
357      */
initChartLegends(JBPanel legends)358     private void initChartLegends(JBPanel legends) {
359         if (ProfilerLogManager.isInfoEnabled()) {
360             LOGGER.info("initChartLegends");
361         }
362         checkAndAdd(legends, totalColor);
363         checkAndAdd(legends, totalLabel);
364         checkAndAdd(legends, javaColor);
365         checkAndAdd(legends, javaLabel);
366         checkAndAdd(legends, nativeColor);
367         checkAndAdd(legends, nativeLabel);
368         checkAndAdd(legends, graphicsColor);
369         checkAndAdd(legends, graphicsLabel);
370         checkAndAdd(legends, stackColor);
371         checkAndAdd(legends, stackLabel);
372         checkAndAdd(legends, codeColor);
373         checkAndAdd(legends, codeLabel);
374         checkAndAdd(legends, othersColor);
375         checkAndAdd(legends, othersLabel);
376     }
377 
checkAndAdd(JBPanel legends, Component component)378     private void checkAndAdd(JBPanel legends, Component component) {
379         if (ProfilerLogManager.isInfoEnabled()) {
380             LOGGER.info("checkAndAdd");
381         }
382         boolean contain = false;
383         for (Component legend : legends.getComponents()) {
384             if (legend.equals(component)) {
385                 contain = true;
386                 break;
387             }
388         }
389         if (!contain) {
390             legends.add(component);
391         }
392         component.setVisible(false);
393     }
394 
buildChartLegends(List<ChartDataModel> lastModels)395     private void buildChartLegends(List<ChartDataModel> lastModels) {
396         new SwingWorker<>() {
397             @Override
398             protected Object doInBackground() {
399                 // Total label
400                 BigDecimal totalMB = divide(new BigDecimal(chart.getListSum(lastModels, 0)), new BigDecimal(NUM_1024));
401                 String totalText;
402                 if (fold) {
403                     String total = totalMB + chart.getAxisLabelY();
404                     totalText = String.format(Locale.ENGLISH, "Total:%s%s", total, chart.getAxisLabelY());
405                     totalColor.setColor(MEMORY_FIRST_PANEL_COLOR);
406                     totalColor.setOpaque(false);
407                     totalColor.setVisible(true);
408                 } else {
409                     totalText = String.format(Locale.ENGLISH, "Total:%s%s", totalMB, chart.getAxisLabelY());
410                     totalColor.setVisible(false);
411                 }
412                 totalLabel.setText(totalText);
413                 totalLabel.setVisible(true);
414                 // Initialize a map of full memory legends
415                 Map<MonitorItemDetail, List<JComponent>> allItemLegendMap = initItemLegends();
416                 // Processing data into legend and remove from allItemLegendMap
417                 lastModels.forEach(model -> parseModelToLegend(model, allItemLegendMap));
418                 // There are only unselected monitoring items in the map, which need to be hidden
419                 allItemLegendMap
420                     .forEach((item, components) -> components.forEach(component -> component.setVisible(false)));
421                 return new Object();
422             }
423         }.execute();
424     }
425 
426     /**
427      * Initialize a map of full memory legends
428      *
429      * @return Map <Monitor item, component of legend>
430      */
initItemLegends()431     private Map<MonitorItemDetail, List<JComponent>> initItemLegends() {
432         if (ProfilerLogManager.isInfoEnabled()) {
433             LOGGER.info("initItemLegends");
434         }
435         Map<MonitorItemDetail, List<JComponent>> map = new HashMap<>();
436         map.put(MEM_JAVA, Arrays.asList(javaColor, javaLabel));
437         map.put(MEM_NATIVE, Arrays.asList(nativeColor, nativeLabel));
438         map.put(MEM_GRAPHICS, Arrays.asList(graphicsColor, graphicsLabel));
439         map.put(MEM_STACK, Arrays.asList(stackColor, stackLabel));
440         map.put(MEM_CODE, Arrays.asList(codeColor, codeLabel));
441         map.put(MEM_OTHERS, Arrays.asList(othersColor, othersLabel));
442         return map;
443     }
444 
445     /**
446      * Processing data into legend and remove from allItemLegendMap
447      *
448      * @param model Data model
449      * @param allItemLegendMap Map of memory legends
450      */
parseModelToLegend(ChartDataModel model, Map<MonitorItemDetail, List<JComponent>> allItemLegendMap)451     private void parseModelToLegend(ChartDataModel model, Map<MonitorItemDetail, List<JComponent>> allItemLegendMap) {
452         MonitorItemDetail itemParam = MonitorItemDetail.getItemByName(model.getName());
453         switch (itemParam) {
454             case MEM_JAVA:
455                 refreshColorText(javaColor, javaLabel, model);
456                 // If the model is saved as the current monitoring item, its components will be displayed
457                 allItemLegendMap.get(MEM_JAVA).forEach(component -> component.setVisible(true));
458                 // After the component is set to display, it is removed from the map. After the loop is completed,
459                 // only unselected monitoring items are left in the map and need to be hidden
460                 allItemLegendMap.remove(MEM_JAVA);
461                 break;
462             case MEM_NATIVE:
463                 refreshColorText(nativeColor, nativeLabel, model);
464                 allItemLegendMap.get(MEM_NATIVE).forEach(component -> component.setVisible(true));
465                 allItemLegendMap.remove(MEM_NATIVE);
466                 break;
467             case MEM_GRAPHICS:
468                 refreshColorText(graphicsColor, graphicsLabel, model);
469                 allItemLegendMap.get(MEM_GRAPHICS).forEach(component -> component.setVisible(true));
470                 allItemLegendMap.remove(MEM_GRAPHICS);
471                 break;
472             case MEM_STACK:
473                 refreshColorText(stackColor, stackLabel, model);
474                 allItemLegendMap.get(MEM_STACK).forEach(component -> component.setVisible(true));
475                 allItemLegendMap.remove(MEM_STACK);
476                 break;
477             case MEM_CODE:
478                 refreshColorText(codeColor, codeLabel, model);
479                 allItemLegendMap.get(MEM_CODE).forEach(component -> component.setVisible(true));
480                 allItemLegendMap.remove(MEM_CODE);
481                 break;
482             case MEM_OTHERS:
483                 refreshColorText(othersColor, othersLabel, model);
484                 allItemLegendMap.get(MEM_OTHERS).forEach(component -> component.setVisible(true));
485                 allItemLegendMap.remove(MEM_OTHERS);
486                 break;
487             default:
488                 break;
489         }
490     }
491 
492     /**
493      * Update the color and text of the legend
494      *
495      * @param colorRect Color component
496      * @param label text label
497      * @param model data
498      */
refreshColorText(ChartLegendColorRect colorRect, JBLabel label, ChartDataModel model)499     private void refreshColorText(ChartLegendColorRect colorRect, JBLabel label, ChartDataModel model) {
500         if (ProfilerLogManager.isInfoEnabled()) {
501             LOGGER.info("refreshColorText");
502         }
503         String showValue = divide(model.getValue(), NUM_1024).toString();
504         String text = String.format(Locale.ENGLISH, "%s:%s%s", model.getName(), showValue, chart.getAxisLabelY());
505         colorRect.setColor(model.getColor());
506         if (!label.getText().equals(text)) {
507             label.setText(text);
508         }
509     }
510 
511     /**
512      * Calculate the total value at a time
513      *
514      * @param time 时间
515      * @param dataMap dataMap
516      * @return Total值
517      */
calcTotal(int time, LinkedHashMap<Integer, List<ChartDataModel>> dataMap)518     private String calcTotal(int time, LinkedHashMap<Integer, List<ChartDataModel>> dataMap) {
519         if (ProfilerLogManager.isInfoEnabled()) {
520             LOGGER.info("calcTotal");
521         }
522         List<ChartDataModel> models = dataMap.get(time);
523         if (models == null || models.size() == 0) {
524             return "";
525         }
526         // Here we get KB, we need to convert it to MB
527         int value = chart.getListSum(models, 0);
528         return divide(value, NUM_1024).toString();
529     }
530 
531     /**
532      * Build tooltip items
533      *
534      * @param time Current time
535      * @param dataMap dataMap
536      * @return List
537      */
buildTooltipItems(int time, LinkedHashMap<Integer, List<ChartDataModel>> dataMap)538     private List<TooltipItem> buildTooltipItems(int time, LinkedHashMap<Integer, List<ChartDataModel>> dataMap) {
539         if (ProfilerLogManager.isInfoEnabled()) {
540             LOGGER.info("buildTooltipItems");
541         }
542         List<TooltipItem> tooltipItems = new ArrayList<>();
543         if (dataMap == null || dataMap.size() == 0 || dataMap.get(time) == null) {
544             return tooltipItems;
545         }
546         for (ChartDataModel model : dataMap.get(time)) {
547             BigDecimal showValue = divide(model.getValue(), NUM_1024);
548             String text = String.format(Locale.ENGLISH, "%s:%s%s", model.getName(), showValue, chart.getAxisLabelY());
549             TooltipItem tooltipItem = new TooltipItem(model.getColor(), text);
550             tooltipItems.add(tooltipItem);
551         }
552         return tooltipItems;
553     }
554 
555     /**
556      * chartLeftMouseClick
557      */
chartLeftMouseClick()558     private void chartLeftMouseClick() {
559         if (ProfilerLogManager.isInfoEnabled()) {
560             LOGGER.info("chartLeftMouseClick");
561         }
562         long sessionId = this.bottomPanel.getSessionId();
563         SessionInfo sessionInfo = SessionManager.getInstance().getSessionInfo(sessionId);
564         if (!sessionInfo.isOfflineMode()
565             && sessionInfo.getDeviceIPPortInfo().getDeviceType() == DeviceType.LEAN_HOS_DEVICE) {
566             return;
567         }
568         if (memoryTreeTablePanel != null) {
569             refreshAgentHeapInfo(sessionId);
570         } else {
571             memoryTreeTablePanel = new MemoryTreeTablePanel(this, sessionId, item.getName());
572             parent.itemChartClick(this);
573             instanceAndDetailSplitter.setOpaque(true);
574             memoryTreeTablePanel.setOpaque(true);
575             agentHeapSplitter.setFirstComponent(memoryTreeTablePanel);
576             // heapView external total panel
577             heapViewPanel = new JBPanel();
578             int height = bottomPanel.getHeight() / 5 * 2;
579             heapViewPanel.setPreferredSize(new Dimension(bottomPanel.getWidth(), height));
580             heapViewPanel.setLayout(new MigLayout("insets 0", "[grow,fill]", "[grow,fill]"));
581             heapViewPanel.add(agentHeapSplitter, "span");
582         }
583         this.add(heapViewPanel, BorderLayout.SOUTH);
584     }
585 
586     /**
587      * refresh agent heap info
588      *
589      * @param sessionId sessionId
590      */
refreshAgentHeapInfo(long sessionId)591     private void refreshAgentHeapInfo(long sessionId) {
592         SwingUtilities.invokeLater(new Runnable() {
593             @Override
594             public void run() {
595                 if (ProfilerLogManager.isInfoEnabled()) {
596                     LOGGER.info("refreshAgentHeapInfo");
597                 }
598                 if (memoryTreeTablePanel != null) {
599                     MemoryAgentHeapInfoPanel memoryAgentHeapInfoPanel =
600                         memoryTreeTablePanel.getMemoryAgentHeapInfoPanel();
601                     if (memoryAgentHeapInfoPanel != null && memoryAgentHeapInfoPanel.getTreeTable() != null) {
602                         DefaultMutableTreeNode root = memoryAgentHeapInfoPanel.initData(sessionId, item.getName());
603                         ListTreeTableModelOnColumns tableModelOnColumns =
604                             new ListTreeTableModelOnColumns(root, memoryAgentHeapInfoPanel.columns);
605                         ExpandTreeTable agentTreeTable = memoryAgentHeapInfoPanel.getTreeTable();
606                         agentTreeTable.setModel(tableModelOnColumns);
607                         JScrollBar scrollBar = agentTreeTable.getVerticalScrollBar();
608                         scrollBar.setValue(0);
609                         scrollBar.removeMouseMotionListener(memoryAgentHeapInfoPanel.getMouseMotionAdapter());
610                         createMouseMotionAdapter(memoryAgentHeapInfoPanel, tableModelOnColumns, agentTreeTable);
611                         scrollBar.addMouseMotionListener(memoryAgentHeapInfoPanel.getMouseMotionAdapter());
612                         AgentTreeTableRowSorter sorter =
613                             new AgentTreeTableRowSorter(agentTreeTable.getTable().getModel());
614                         sorter.setListener((columnIndex, sortOrder) -> {
615                             if (columnIndex <= 0 || columnIndex > memoryAgentHeapInfoPanel.columns.length) {
616                                 return;
617                             }
618                             if (sortOrder == SortOrder.ASCENDING) {
619                                 AgentTreeTableRowSorter.sortDescTree(memoryAgentHeapInfoPanel,
620                                     memoryAgentHeapInfoPanel.columns[columnIndex].getName(), tableModelOnColumns);
621                             } else {
622                                 AgentTreeTableRowSorter.sortTree(memoryAgentHeapInfoPanel,
623                                     memoryAgentHeapInfoPanel.columns[columnIndex].getName(), tableModelOnColumns);
624                             }
625                             tableModelOnColumns.reload();
626                         });
627                         agentTreeTable.getTable().setRowSorter(sorter);
628                         agentHeapSplitter.setSecondComponent(new JBSplitter(false, 1));
629                     }
630                 }
631             }
632         });
633     }
634 
createMouseMotionAdapter(MemoryAgentHeapInfoPanel memoryAgentHeapInfoPanel, ListTreeTableModelOnColumns tableModelOnColumns, ExpandTreeTable agentTreeTable)635     private void createMouseMotionAdapter(MemoryAgentHeapInfoPanel memoryAgentHeapInfoPanel,
636         ListTreeTableModelOnColumns tableModelOnColumns, ExpandTreeTable agentTreeTable) {
637         memoryAgentHeapInfoPanel.setMouseMotionAdapter(new MouseMotionAdapter() {
638             @Override
639             public void mouseDragged(MouseEvent mouseEvent) {
640                 JScrollBar jScrollBar = null;
641                 Object sourceObject = mouseEvent.getSource();
642                 if (sourceObject instanceof JScrollBar) {
643                     jScrollBar = (JScrollBar) sourceObject;
644                     BoundedRangeModel model = jScrollBar.getModel();
645                     if (model.getExtent() + model.getValue() == model.getMaximum()) {
646                         ListTreeTableModelOnColumns nodeModel = null;
647                         Object modelObject = agentTreeTable.getTree().getModel();
648                         if (modelObject instanceof ListTreeTableModelOnColumns) {
649                             nodeModel = (ListTreeTableModelOnColumns) modelObject;
650                             DefaultMutableTreeNode rootNode = null;
651                             Object rootObject = nodeModel.getRoot();
652                             if (rootObject instanceof DefaultMutableTreeNode) {
653                                 rootNode = (DefaultMutableTreeNode) rootObject;
654                                 int index = memoryAgentHeapInfoPanel.getAllAgentDatas()
655                                     .indexOf(memoryAgentHeapInfoPanel.getLastDataNode());
656                                 List<AgentHeapBean> list = memoryAgentHeapInfoPanel
657                                     .listCopy(memoryAgentHeapInfoPanel.getAllAgentDatas(), index, index + 20);
658                                 for (AgentHeapBean agentDataNode : list) {
659                                     DefaultMutableTreeNode defaultMutableTreeNode =
660                                         new DefaultMutableTreeNode(agentDataNode);
661                                     tableModelOnColumns
662                                         .insertNodeInto(defaultMutableTreeNode, rootNode, rootNode.getChildCount());
663                                     memoryAgentHeapInfoPanel.setLastDataNode(agentDataNode);
664                                 }
665                             }
666                         }
667                     }
668                 }
669             }
670         });
671     }
672 
673     /**
674      * Secondary treeTable interface
675      *
676      * @param sessionId sessionId
677      * @param clazzId clazzId
678      * @param className className
679      * @param chartName chartName
680      * @return JBPanel
681      */
setSecondLevelTreeTable(long sessionId, int clazzId, String className, String chartName)682     public JBPanel setSecondLevelTreeTable(long sessionId, int clazzId, String className, String chartName) {
683         if (ProfilerLogManager.isInfoEnabled()) {
684             LOGGER.info("setSecondLevelTreeTable");
685         }
686         agentHeapSplitter.setProportion(LayoutConstants.PROPORTION_SEGMENT);
687         // instance Table panel
688         JBPanel instanceView = new JBPanel();
689         instanceView.setLayout(new BorderLayout());
690         instanceView.setOpaque(true);
691         instanceView.setBackground(JBColor.background().darker());
692 
693         setTitleStyle(className, instanceView, 1);
694 
695         instanceView.setPreferredSize(new Dimension(INSTANCE_TITLE_WIDTH, NUM_418));
696         // Table header
697         Vector<String> columnNames = new Vector<>();
698         columnNames.add("instance");
699         columnNames.add("allocTime");
700         columnNames.add("DealloTime");
701         columnNames.add("InstanceId");
702         // Display JBTable
703         DefaultTableModel defaultTableModel = new DefaultTableModel() {
704             /**
705              * isCellEditable
706              *
707              * @param row row
708              * @param column column
709              * @return boolean
710              */
711             public boolean isCellEditable(int row, int column) {
712                 return false;
713             }
714         };
715         defaultTableModel.setColumnIdentifiers(columnNames);
716         instanceViewTable = new JBTable(defaultTableModel);
717         setExtracted(defaultTableModel, instanceViewTable);
718         // Initialize table data
719         initData(defaultTableModel, clazzId, className, sessionId, chartName);
720         JBScrollPane jScrollPane = new JBScrollPane(instanceViewTable);
721         jScrollPane.setPreferredSize(new Dimension(INSTANCE_TITLE_WIDTH, INSTANCE_PANE_HEIGHT));
722         instanceView.add(jScrollPane, BorderLayout.CENTER);
723         return instanceView;
724     }
725 
726     /**
727      * 初始化table 表格
728      *
729      * @param model model
730      * @param cId cId
731      * @param className className
732      * @param sessionId long
733      * @param chartName chartName
734      */
initData(DefaultTableModel model, Integer cId, String className, long sessionId, String chartName)735     public void initData(DefaultTableModel model, Integer cId, String className, long sessionId, String chartName) {
736         if (ProfilerLogManager.isInfoEnabled()) {
737             LOGGER.info("initData");
738         }
739         MemoryInstanceManager memoryInstanceManager = new MemoryInstanceManager();
740         ChartStandard standard = ProfilerChartsView.sessionMap.get(sessionId).getPublisher().getStandard();
741         long firstTime = standard.getFirstTimestamp();
742         ChartDataRange selectedRange = standard.getSelectedRange(chartName);
743         long endTime = selectedRange.getEndTime() + firstTime;
744         List<MemoryInstanceInfo> memoryInstanceInfos = memoryInstanceManager.getMemoryInstanceInfos(cId, 0L, endTime);
745         memoryInstanceInfos.forEach(memoryInstanceInfo -> {
746             long deallocTime = memoryInstanceInfo.getDeallocTime();
747             long alloc = TimeUnit.MILLISECONDS.toMicros(memoryInstanceInfo.getAllocTime() - firstTime);
748             String allocTime = getSemiSimplifiedClockString(alloc);
749             String deAllocTime = " - ";
750             if (deallocTime != 0) {
751                 long deAllocations = TimeUnit.MILLISECONDS.toMicros(memoryInstanceInfo.getDeallocTime() - firstTime);
752                 deAllocTime = getSemiSimplifiedClockString(deAllocations);
753             }
754             Integer instanceId = memoryInstanceInfo.getInstanceId();
755             Vector<Object> rowData = new Vector<>();
756             rowData.add(className);
757             rowData.add(allocTime);
758             rowData.add(deAllocTime);
759             rowData.add(instanceId);
760             model.addRow(rowData);
761         });
762     }
763 
764     /**
765      * Return a formatted time String in the form of "hh:mm:ss.sss"".
766      * Hide hours value if both hours and minutes value are zero.
767      * Default format for Tooltips.
768      *
769      * @param micro micro
770      * @return String
771      */
getSemiSimplifiedClockString(long micro)772     public String getSemiSimplifiedClockString(long micro) {
773         if (ProfilerLogManager.isInfoEnabled()) {
774             LOGGER.info("getSemiSimplifiedClockString");
775         }
776         long micros = Math.max(0, micro);
777         return getFullClockString(micros);
778     }
779 
780     /**
781      * Return a formatted time String in the form of "hh:mm:ss.sss".
782      * Default format for Range description.
783      *
784      * @param micro micro
785      * @return String
786      */
getFullClockString(long micro)787     public String getFullClockString(long micro) {
788         if (ProfilerLogManager.isInfoEnabled()) {
789             LOGGER.info("getFullClockString");
790         }
791         long micros = Math.max(0, micro);
792         long milli = TimeUnit.MICROSECONDS.toMillis(micros) % TimeUnit.SECONDS.toMillis(1);
793         long sec = TimeUnit.MICROSECONDS.toSeconds(micros) % TimeUnit.MINUTES.toSeconds(1);
794         long min = TimeUnit.MICROSECONDS.toMinutes(micros) % TimeUnit.HOURS.toMinutes(1);
795         long hour = TimeUnit.MICROSECONDS.toHours(micros);
796         return String.format(Locale.ENGLISH, "%02d:%02d:%02d.%03d", hour, min, sec, milli);
797     }
798 
setExtracted(DefaultTableModel model, JBTable table)799     private void setExtracted(DefaultTableModel model, JBTable table) {
800         if (ProfilerLogManager.isInfoEnabled()) {
801             LOGGER.info("setExtracted");
802         }
803         table.getTableHeader().setFont(new Font("PingFang SC", Font.PLAIN, LayoutConstants.FONT_SIZE));
804         table.setFont(new Font("PingFang SC", Font.PLAIN, LayoutConstants.TWELVE));
805         table.setOpaque(true);
806         table.setShowHorizontalLines(false);
807         table.getTableHeader().getColumnModel().getColumn(3).setMaxWidth(0);
808         table.getTableHeader().getColumnModel().getColumn(3).setMinWidth(0);
809         table.getTableHeader().getColumnModel().getColumn(3).setPreferredWidth(0);
810         RowSorter<TableModel> sorter = new TableRowSorter<>(model);
811         table.setRowSorter(sorter);
812     }
813 
814     /**
815      * Three-level treeTable interface
816      *
817      * @param sessionId sessionId
818      * @param instanceId instanceId
819      * @param name name
820      * @return JBPanel
821      */
setThirdLevelTreeTable(long sessionId, int instanceId, String name)822     public JBPanel setThirdLevelTreeTable(long sessionId, int instanceId, String name) {
823         if (ProfilerLogManager.isInfoEnabled()) {
824             LOGGER.info("setThirdLevelTreeTable");
825         }
826         agentHeapSplitter.setProportion(PROPORTION_SEGMENT_VIEW);
827         instanceAndDetailSplitter.setProportion(PROPORTION_SEGMENT_HEAP);
828         // Reserved Tree Table panel
829         JBPanel fieldsView = new JBPanel(new BorderLayout());
830         fieldsView.setOpaque(true);
831         setTitleStyle(name, fieldsView, 0);
832         fieldsView.setPreferredSize(new Dimension(NUM_384, NUM_418));
833         Vector<String> columnNames = new Vector<>();
834         columnNames.add("Allocation Call Stack");
835         DefaultTableModel model = new DefaultTableModel() {
836             /**
837              * Returns true regardless of parameter values.
838              *
839              * @param row the row whose value is to be queried
840              * @param column the column whose value is to be queried
841              * @return true
842              */
843             @Override
844             public boolean isCellEditable(int row, int column) {
845                 return false;
846             }
847         };
848         model.setColumnIdentifiers(columnNames);
849         JBTable callStackTable = new JBTable(model);
850         DefaultTableCellRenderer defaultCellRender = new DefaultTableCellRenderer() {
851             @Override
852             public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
853                 boolean hasFocus, int row, int column) {
854                 JLabel jLabel = null;
855                 Object jLabelObject =
856                     super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
857                 if (jLabelObject instanceof JLabel) {
858                     jLabel = (JLabel) jLabelObject;
859                     jLabel.setIcon(AllIcons.Nodes.Method);
860                 }
861                 return jLabel;
862             }
863         };
864         defaultCellRender.getTableCellRendererComponent(callStackTable, null, false, false, 1, 0);
865         callStackTable.getColumnModel().getColumn(0).setCellRenderer(defaultCellRender);
866         MemoryInstanceDetailsManager detailsManager = new MemoryInstanceDetailsManager();
867         ArrayList<MemoryInstanceDetailsInfo> detailsInfos = detailsManager.getMemoryInstanceDetailsInfos(instanceId);
868         detailsInfos.forEach(detailsInfo -> {
869             Vector<String> rowData = new Vector<>();
870             rowData.add(
871                 detailsInfo.getMethodName() + ":" + detailsInfo.getLineNumber() + "," + detailsInfo.getClassName()
872                     + "; (" + detailsInfo.getFieldName() + ")");
873             model.addRow(rowData);
874         });
875         callStackTable.setShowHorizontalLines(false);
876         JBScrollPane jScrollPane = new JBScrollPane(callStackTable);
877         jScrollPane.setPreferredSize(new Dimension(INSTANCE_TITLE_WIDTH, INSTANCE_SCROLL_HEIGHT));
878         fieldsView.add(jScrollPane, BorderLayout.CENTER);
879         return fieldsView;
880     }
881 
setTitleStyle(String name, JBPanel viewStyle, int status)882     private void setTitleStyle(String name, JBPanel viewStyle, int status) {
883         if (ProfilerLogManager.isInfoEnabled()) {
884             LOGGER.info("setTitleStyle");
885         }
886         JBLabel jbLabel = new JBLabel();
887         if (status == 0) {
888             jbLabel.setText("  Instance Details-" + name);
889         } else {
890             jbLabel.setText("  Instance view");
891         }
892         Font font = new Font("PingFang SC", Font.PLAIN, LayoutConstants.FONT_SIZE);
893         jbLabel.setFont(font);
894         JBLabel closeLabel = new JBLabel(AllIcons.Actions.Close);
895         closeLabel.addMouseListener(new MouseAdapter() {
896             @Override
897             public void mouseClicked(MouseEvent mouseEvent) {
898                 super.mouseClicked(mouseEvent);
899                 if (status == 0) {
900                     instanceAndDetailSplitter.setSecondComponent(new JBSplitter(false, 1));
901                 } else {
902                     agentHeapSplitter.setSecondComponent(new JBSplitter(false, 1));
903                 }
904             }
905         });
906 
907         JBPanel titlePanel = new JBPanel(new BorderLayout());
908         titlePanel.setOpaque(true);
909         titlePanel.setBackground(JBColor.background().darker());
910         titlePanel.setPreferredSize(new Dimension(NUM_384, INSTANCE_TITLE_HEIGHT));
911         titlePanel.add(jbLabel, BorderLayout.WEST);
912         titlePanel.add(closeLabel, BorderLayout.EAST);
913         viewStyle.add(titlePanel, BorderLayout.NORTH);
914     }
915 
chartRightMouseClick()916     private void chartRightMouseClick() {
917         if (heapViewPanel != null) {
918             this.remove(heapViewPanel);
919             heapViewPanel = null;
920             memoryTreeTablePanel = null;
921         }
922     }
923 
chartMouseDragged()924     private void chartMouseDragged() {
925         if (ProfilerLogManager.isInfoEnabled()) {
926             LOGGER.info("chartMouseDragged");
927         }
928     }
929 
chartMouseRelease()930     private void chartMouseRelease() {
931         long sessionId = this.bottomPanel.getSessionId();
932         SessionInfo sessionInfo = SessionManager.getInstance().getSessionInfo(sessionId);
933         if (!sessionInfo.isOfflineMode()
934             && sessionInfo.getDeviceIPPortInfo().getDeviceType() == DeviceType.LEAN_HOS_DEVICE) {
935             return;
936         }
937         refreshAgentHeapInfo(sessionId);
938     }
939 
940     private class MemoryTitleView extends JBPanel {
941         /**
942          * Save the components should be hidden when item fold
943          */
944         private JBPanel hiddenComp;
945 
MemoryTitleView()946         MemoryTitleView() {
947             this.setLayout(new FlowLayout(FlowLayout.LEFT));
948             initFixedComps();
949             initHiddenComponents();
950             this.setBackground(JBColor.background().brighter());
951         }
952 
initFixedComps()953         private void initFixedComps() {
954             if (ProfilerLogManager.isInfoEnabled()) {
955                 LOGGER.info("initFixedComps");
956             }
957             foldBtn = new JBLabel();
958             foldBtn.setName(UtConstant.UT_MEMORY_ITEM_VIEW_FOLD);
959             foldBtn.setIcon(AllIcons.General.ArrowRight);
960             this.add(foldBtn);
961             foldBtn.addMouseListener(new MouseAdapter() {
962                 @Override
963                 public void mouseClicked(MouseEvent event) {
964                     foldBtnClick();
965                 }
966             });
967             JBLabel title = new JBLabel(item.getName());
968             this.add(title);
969         }
970 
foldBtnClick()971         private void foldBtnClick() {
972             if (ProfilerLogManager.isInfoEnabled()) {
973                 LOGGER.info("foldBtnClick");
974             }
975             fold = !fold;
976             // Item fold, buttons hide
977             hiddenComp.setVisible(!fold);
978             if (fold) {
979                 chart.setFold(true);
980                 chart.setEnableSelect(false);
981                 chart.getTooltip().hideTip();
982                 foldBtn.setIcon(AllIcons.General.ArrowRight);
983                 if (heapViewPanel != null) {
984                     MemoryItemView.this.remove(heapViewPanel);
985                     heapViewPanel = null;
986                 }
987                 if (memoryTreeTablePanel != null) {
988                     MemoryItemView.this.remove(memoryTreeTablePanel);
989                     memoryTreeTablePanel = null;
990                 }
991             } else {
992                 EventTrackUtils.getInstance().trackApplicationMemory();
993                 // Uncheck the box after re-expanding
994                 bottomPanel.getPublisher().getStandard().clearSelectedRange(item.getName());
995                 chart.setFold(false);
996                 chart.setEnableSelect(true);
997                 foldBtn.setIcon(AllIcons.General.ArrowDown);
998             }
999             parent.itemFoldOrExpend(fold, MemoryItemView.this);
1000             // Initialize the maximum value of Y axis here,  because it may change after fold/expand
1001             chart.initMaxUnitY();
1002             chartObserver.setChartFold(fold);
1003         }
1004 
initHiddenComponents()1005         private void initHiddenComponents() {
1006             if (ProfilerLogManager.isInfoEnabled()) {
1007                 LOGGER.info("initHiddenComponents");
1008             }
1009             hiddenComp = new JBPanel(new FlowLayout(FlowLayout.LEFT));
1010             hiddenComp.setBackground(JBColor.background().brighter());
1011             this.add(hiddenComp);
1012             // Add components
1013             hiddenComp.add(new DottedLine());
1014             initDetailCfgBtn();
1015             initHeapDumpBtn();
1016             hiddenComp.add(new DottedLine());
1017             initNativeBtn();
1018             initNativeConfigBtn();
1019             // The initial state is folded and hiddenComp needs to be hidden
1020             hiddenComp.setVisible(false);
1021         }
1022 
initDetailCfgBtn()1023         private void initDetailCfgBtn() {
1024             if (ProfilerLogManager.isInfoEnabled()) {
1025                 LOGGER.info("initDetailCfgBtn");
1026             }
1027             detailCfgBtn = new JBLabel(IconLoader.getIcon("/images/icon_dataselection_normal.png", getClass()));
1028             detailCfgBtn.setName(UtConstant.UT_MEMORY_ITEM_VIEW_DETAIL);
1029             hiddenComp.add(detailCfgBtn);
1030             MemoryItemPopupMenu memoryPopupMenu = new MemoryItemPopupMenu(bottomPanel.getSessionId(), chartObserver);
1031             detailCfgBtn.addMouseListener(new MouseAdapter() {
1032                 @Override
1033                 public void mouseClicked(MouseEvent mouseEvent) {
1034                     memoryPopupMenu.showMemoryItems(detailCfgBtn, mouseEvent);
1035                 }
1036             });
1037         }
1038 
initHeapDumpBtn()1039         private void initHeapDumpBtn() {
1040             if (ProfilerLogManager.isInfoEnabled()) {
1041                 LOGGER.info("initHeapDumpBtn");
1042             }
1043             heapDumpBtn = new JBLabel();
1044             heapDumpBtn.setName(UtConstant.UT_MEMORY_ITEM_VIEW_HEAP_DUMP);
1045             heapDumpBtn.setToolTipText("Memory heap dump");
1046             Icon icon;
1047             // Add support for heap dump in specific processes
1048             DeviceIPPortInfo deviceInfoBySessionId =
1049                 SessionManager.getInstance().getDeviceInfoBySessionId(bottomPanel.getSessionId());
1050             ProcessInfo processInfo =
1051                 SessionManager.getInstance().getSessionInfo(bottomPanel.getSessionId()).getProcessInfo();
1052             boolean isDebuggerProcess =
1053                 ProcessManager.getInstance().checkIsDebuggerProcess(deviceInfoBySessionId, processInfo);
1054             if (isDebuggerProcess) {
1055                 icon = IconLoader.getIcon("/images/icon_heap_dump_normal.png", getClass());
1056                 heapDumpBtn.addMouseListener(new MouseAdapter() {
1057                     @Override
1058                     public void mouseClicked(MouseEvent mouseEvent) {
1059                         super.mouseClicked(mouseEvent);
1060                         EventTrackUtils.getInstance().trackApplicationHprof();
1061                         int showTime = bottomPanel.getTimeline().getEndTime();
1062                         Date date = new Date();
1063                         StringWriter stringWriter = new StringWriter();
1064                         PrintWriter printWriter = new PrintWriter(stringWriter);
1065                         date.setTime(showTime);
1066                         printWriter.format("%1$tM:%1$tS.%tL", date);
1067                         printWriter.flush();
1068                         bottomPanel.getTaskScenePanelChart()
1069                             .createSessionList(LayoutConstants.HEAP_DUMP, stringWriter.toString(),
1070                                 bottomPanel.getSessionId(), null);
1071                     }
1072                 });
1073             } else {
1074                 icon = IconLoader.getIcon("/images/icon_heap_dump_grey.png", getClass());
1075             }
1076             heapDumpBtn.setIcon(icon);
1077             hiddenComp.add(heapDumpBtn);
1078         }
1079 
initNativeBtn()1080         private void initNativeBtn() {
1081             if (ProfilerLogManager.isInfoEnabled()) {
1082                 LOGGER.info("initNativeBtn");
1083             }
1084             nativeBtn = new JButton(" Record native allocations ");
1085             DeviceType deviceType = SessionManager.getInstance().getDeviceType(bottomPanel.getSessionId());
1086             if (deviceType == DeviceType.FULL_HOS_DEVICE) {
1087                 nativeBtn.setEnabled(false);
1088                 nativeBtn.setBackground(JBColor.background().brighter());
1089             } else {
1090                 nativeBtn.setEnabled(true);
1091                 nativeBtn.setName("nativeBtn");
1092                 nativeBtn.setOpaque(false);
1093                 nativeBtn.addMouseListener(new MouseAdapter() {
1094                     @Override
1095                     public void mouseClicked(MouseEvent mouseEvent) {
1096                         super.mouseClicked(mouseEvent);
1097                         long sessionId = bottomPanel.getSessionId();
1098                         SessionInfo sessionInfo = SessionManager.getInstance().getSessionInfo(sessionId);
1099                         if (Objects.nonNull(sessionInfo)) {
1100                             DeviceIPPortInfo deviceIPPortInfo = sessionInfo.getDeviceIPPortInfo();
1101                             ProcessInfo processInfo = new ProcessInfo();
1102                             processInfo.setProcessId(sessionInfo.getPid());
1103                             processInfo.setProcessName(sessionInfo.getProcessName());
1104                             long sessionOperationId = SessionManager.getInstance()
1105                                 .createSessionOperationStart(deviceIPPortInfo, processInfo, NATIVE_HOOK_PLUGIN_NAME);
1106                             if (sessionOperationId != Constant.ABNORMAL) {
1107                                 sessionInfo.setSecondSessionId(sessionOperationId);
1108                                 bottomPanel.getTaskScenePanelChart().getjButtonStop()
1109                                     .setIcon(AllIcons.Process.ProgressResumeHover);
1110                                 bottomPanel.getTaskScenePanelChart().getjButtonStop().setToolTipText("Start");
1111                                 bottomPanel.getPublisher().pauseRefresh();
1112                                 bottomPanel.setPause(true);
1113                                 new NativeRecordDialog(bottomPanel, sessionId);
1114                             } else {
1115                                 JPanel promptMessage = new JPanel(new BorderLayout());
1116                                 JBLabel messageLabel = new JBLabel("Create Session Failed");
1117                                 messageLabel.setPreferredSize(new Dimension(100, 70));
1118                                 promptMessage.add(messageLabel, BorderLayout.CENTER);
1119                                 new CustomDialog("prompt", promptMessage).show();
1120                             }
1121                         }
1122                     }
1123                 });
1124                 nativeBtn.setBorder(BorderFactory.createEmptyBorder());
1125             }
1126             hiddenComp.add(nativeBtn);
1127         }
1128 
1129         /**
1130          * init Native ConfigBtn
1131          */
initNativeConfigBtn()1132         private void initNativeConfigBtn() {
1133             JBLabel configButton = new JBLabel();
1134             configButton.setIcon(IconLoader.getIcon("/images/icon_cpu_perfConfig.png", CpuItemView.class));
1135             configButton.setOpaque(false);
1136             configButton.addMouseListener(new MouseAdapter() {
1137                 @Override
1138                 public void mouseClicked(MouseEvent event) {
1139                     new NativeConfigDialog();
1140                 }
1141             });
1142             hiddenComp.add(configButton);
1143         }
1144     }
1145 
getHeapViewPanel()1146     public JBPanel getHeapViewPanel() {
1147         return heapViewPanel;
1148     }
1149 }
1150