• 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.javaagent;
17 
18 import com.intellij.ui.HighlightableCellRenderer;
19 import com.intellij.ui.JBSplitter;
20 import com.intellij.ui.components.JBPanel;
21 import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
22 import com.intellij.ui.treeStructure.treetable.TreeColumnInfo;
23 import com.intellij.util.ui.ColumnInfo;
24 import ohos.devtools.datasources.databases.databaseapi.DataBaseApi;
25 import ohos.devtools.datasources.utils.profilerlog.ProfilerLogManager;
26 import ohos.devtools.services.memory.agentbean.AgentHeapBean;
27 import ohos.devtools.services.memory.agentdao.ClassInfoManager;
28 import ohos.devtools.services.memory.agentdao.MemoryHeapManager;
29 import ohos.devtools.views.charts.model.ChartDataRange;
30 import ohos.devtools.views.charts.model.ChartStandard;
31 import ohos.devtools.views.common.treetable.ExpandTreeTable;
32 import ohos.devtools.views.common.treetable.TreeTableColumn;
33 import ohos.devtools.views.layout.chartview.ProfilerChartsView;
34 import ohos.devtools.views.layout.chartview.memory.MemoryItemView;
35 import org.apache.commons.lang3.StringUtils;
36 import org.apache.logging.log4j.LogManager;
37 import org.apache.logging.log4j.Logger;
38 
39 import javax.swing.BoundedRangeModel;
40 import javax.swing.JLabel;
41 import javax.swing.JScrollBar;
42 import javax.swing.SortOrder;
43 import javax.swing.SwingWorker;
44 import javax.swing.table.DefaultTableCellRenderer;
45 import javax.swing.tree.DefaultMutableTreeNode;
46 import javax.swing.tree.TreePath;
47 import java.awt.BorderLayout;
48 import java.awt.event.MouseAdapter;
49 import java.awt.event.MouseEvent;
50 import java.awt.event.MouseMotionAdapter;
51 import java.util.ArrayList;
52 import java.util.List;
53 import java.util.Objects;
54 
55 import static ohos.devtools.views.common.Constant.MEMORY_AGENT_INIT_COUNT;
56 
57 /**
58  * MemoryAgentHeapInfoPanel
59  *
60  * @since : 2021/10/25
61  */
62 public class MemoryAgentHeapInfoPanel extends JBPanel {
63     private static final Logger LOGGER = LogManager.getLogger(MemoryAgentHeapInfoPanel.class);
64 
65     /**
66      * columns
67      */
68     public final ColumnInfo[] columns =
69         new ColumnInfo[] {new TreeColumnInfo("Class Name"), new TreeTableColumn<>("Allocations", AgentHeapBean.class) {
70             @Override
71             public String getColumnValue(AgentHeapBean nodeData) {
72                 return String.valueOf(nodeData.getAgentAllocationsCount());
73             }
74         }, new TreeTableColumn<>("Deallocations", AgentHeapBean.class) {
75             @Override
76             public String getColumnValue(AgentHeapBean nodeData) {
77                 return String.valueOf(nodeData.getAgentDeAllocationsCount());
78             }
79         }, new TreeTableColumn<>("Total Count", AgentHeapBean.class) {
80             @Override
81             public String getColumnValue(AgentHeapBean nodeData) {
82                 return String.valueOf(nodeData.getAgentTotalInstanceCount());
83             }
84         }, new TreeTableColumn<>("Shallow Size", AgentHeapBean.class) {
85             @Override
86             public String getColumnValue(AgentHeapBean nodeData) {
87                 return String.valueOf(nodeData.getAgentTotalshallowSize());
88             }
89         }};
90 
91     /**
92      * allAgentDatas
93      */
94     private List<AgentHeapBean> allAgentDatas;
95 
96     /**
97      * lastDataNode
98      */
99     private AgentHeapBean lastDataNode;
100 
101     /**
102      * mouseMotionAdapter
103      */
104     private MouseMotionAdapter mouseMotionAdapter;
105 
106     private ExpandTreeTable treeTable;
107 
108     /**
109      * mouseListener
110      */
111     private MouseAdapter mouseListener;
112 
113     /**
114      * MemoryAgentHeapInfoPanel
115      *
116      * @param memoryItemView memoryItemView
117      * @param sessionId long
118      * @param chartName String
119      */
MemoryAgentHeapInfoPanel(MemoryItemView memoryItemView, long sessionId, String chartName)120     public MemoryAgentHeapInfoPanel(MemoryItemView memoryItemView, long sessionId, String chartName) {
121         if (ProfilerLogManager.isInfoEnabled()) {
122             LOGGER.info("MemoryAgentHeapInfoPanel");
123         }
124         setLayout(new BorderLayout());
125         SwingWorker<ExpandTreeTable, Object> task = new SwingWorker<>() {
126             /**
127              * doInBackground
128              *
129              * @return JTreeTable
130              * @throws Exception Exception
131              */
132             @Override
133             protected ExpandTreeTable doInBackground() {
134                 return createTable(memoryItemView, sessionId, chartName);
135             }
136 
137             /**
138              * done
139              */
140             @Override
141             protected void done() {
142                 if (Objects.nonNull(treeTable)) {
143                     add(treeTable);
144                 }
145             }
146         };
147         task.execute();
148     }
149 
150     /**
151      * Copy list according to subscript
152      *
153      * @param dataList dataList
154      * @param startIndex startIndex
155      * @param endIndex endIndex
156      * @return list
157      */
listCopy(List<AgentHeapBean> dataList, int startIndex, int endIndex)158     public List<AgentHeapBean> listCopy(List<AgentHeapBean> dataList, int startIndex, int endIndex) {
159         if (ProfilerLogManager.isInfoEnabled()) {
160             LOGGER.info("listCopy");
161         }
162         List list = new ArrayList();
163         for (int index = startIndex + 1; index < endIndex; index++) {
164             if (index < dataList.size()) {
165                 AgentHeapBean agentHeapBean = dataList.get(index);
166                 if (agentHeapBean != null) {
167                     list.add(agentHeapBean);
168                 }
169             }
170         }
171         return list;
172     }
173 
174     /**
175      * createTreeTable
176      *
177      * @param memoryItemView memoryItemView
178      * @param sessionId long
179      * @param chartName String
180      * @return ExpandTreeTable
181      */
createTable(MemoryItemView memoryItemView, long sessionId, String chartName)182     public ExpandTreeTable createTable(MemoryItemView memoryItemView, long sessionId, String chartName) {
183         if (ProfilerLogManager.isInfoEnabled()) {
184             LOGGER.info("createTable");
185         }
186         DefaultMutableTreeNode root = initData(sessionId, chartName);
187         ListTreeTableModelOnColumns tableModelOnColumns = new ListTreeTableModelOnColumns(root, columns);
188         ExpandTreeTable treeTables = new ExpandTreeTable(tableModelOnColumns);
189         DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer();
190         defaultTableCellRenderer.setHorizontalAlignment(JLabel.RIGHT);
191         treeTables.getTable().setDefaultRenderer(Object.class, defaultTableCellRenderer);
192         JScrollBar tableVerticalScrollBar1 = treeTables.getVerticalScrollBar();
193         getMouseMotionAdapter(tableModelOnColumns, treeTables);
194         tableVerticalScrollBar1.addMouseMotionListener(mouseMotionAdapter);
195         AgentTreeTableRowSorter sorter = new AgentTreeTableRowSorter(treeTables.getTable().getModel());
196         sorter.setListener((columnIndex, sortOrder) -> {
197             if (columnIndex <= 0 || columnIndex > columns.length) {
198                 return;
199             }
200             if (sortOrder == SortOrder.ASCENDING) {
201                 AgentTreeTableRowSorter
202                     .sortDescTree(MemoryAgentHeapInfoPanel.this, columns[columnIndex].getName(), tableModelOnColumns);
203             } else {
204                 AgentTreeTableRowSorter
205                     .sortTree(MemoryAgentHeapInfoPanel.this, columns[columnIndex].getName(), tableModelOnColumns);
206             }
207             tableModelOnColumns.reload();
208         });
209         treeTables.getTree().setRootVisible(true);
210         treeTables.getTree().setExpandsSelectedPaths(true);
211         treeTables.getTable().setRowSorter(sorter);
212         treeTables.getTree().setCellRenderer(new HighlightableCellRenderer());
213         treeTables.getTree().getExpandableItemsHandler().setEnabled(true);
214         mouseListener = getTreeTableMouseListener(memoryItemView, sessionId, chartName);
215         treeTables.getTable().addMouseListener(mouseListener);
216         treeTables.getTree().addMouseListener(mouseListener);
217         treeTable = treeTables;
218         return treeTables;
219     }
220 
getTreeTableMouseListener(MemoryItemView memoryItemView, long sessionId, String chartName)221     private MouseAdapter getTreeTableMouseListener(MemoryItemView memoryItemView, long sessionId, String chartName) {
222         return new MouseAdapter() {
223             /**
224              * mouseClicked
225              *
226              * @param mouseEvent mouseEvent
227              */
228             @Override
229             public void mouseClicked(MouseEvent mouseEvent) {
230                 if (mouseEvent.getClickCount() == 1) {
231                     int selectedRow = treeTable.getTable().getSelectedRow();
232                     TreePath treePath = treeTable.getTree().getPathForRow(selectedRow);
233                     if (treePath == null) {
234                         return;
235                     }
236                     Object rowNode = treePath.getLastPathComponent();
237                     if (rowNode instanceof DefaultMutableTreeNode) {
238                         DefaultMutableTreeNode rowData = (DefaultMutableTreeNode) rowNode;
239                         Object dataNode = rowData.getUserObject();
240                         if (dataNode instanceof AgentHeapBean) {
241                             String className = ((AgentHeapBean) dataNode).getAgentClazzName();
242                             int cid = new ClassInfoManager().getClassIdByClassName(className);
243                             // Need to be obtained from the first-level interface
244                             JBPanel instanceViewPanel =
245                                 memoryItemView.setSecondLevelTreeTable(sessionId, cid, className, chartName);
246                             memoryItemView.instanceAndDetailSplitter.setFirstComponent(instanceViewPanel);
247                             memoryItemView.instanceAndDetailSplitter.setSecondComponent(new JBSplitter(false, 1));
248                             if (memoryItemView.instanceViewTable != null) {
249                                 memoryItemView.instanceViewTable.addMouseListener(new MouseAdapter() {
250                                     /**
251                                      * mouseClicked
252                                      *
253                                      * @param mouseEvent mouseEvent
254                                      */
255                                     @Override
256                                     public void mouseClicked(MouseEvent mouseEvent) {
257                                         int selectedRow = memoryItemView.instanceViewTable.getSelectedRow();
258                                         if (selectedRow < 0) {
259                                             return;
260                                         }
261                                         Object id = memoryItemView.instanceViewTable.getValueAt(selectedRow, 3);
262                                         if (id instanceof Integer) {
263                                             Integer instanceId = (Integer) id;
264                                             JBPanel callStack =
265                                                 memoryItemView.setThirdLevelTreeTable(sessionId, instanceId, className);
266                                             memoryItemView.instanceAndDetailSplitter.setSecondComponent(callStack);
267                                         }
268                                     }
269                                 });
270                             }
271                             memoryItemView.agentHeapSplitter
272                                 .setSecondComponent(memoryItemView.instanceAndDetailSplitter);
273                         }
274                     }
275                 }
276             }
277         };
278     }
279 
280     /**
281      * getMouseMotionAdapter
282      *
283      * @param tableModelOnColumns tableModelOnColumns
284      * @param treeTables treeTables
285      */
286     private void getMouseMotionAdapter(ListTreeTableModelOnColumns tableModelOnColumns, ExpandTreeTable treeTables) {
287         mouseMotionAdapter = new MouseMotionAdapter() {
288             @Override
289             public void mouseDragged(MouseEvent mouseEvent) {
290                 JScrollBar jScrollBar = null;
291                 Object sourceObject = mouseEvent.getSource();
292                 if (sourceObject instanceof JScrollBar) {
293                     jScrollBar = (JScrollBar) sourceObject;
294                     BoundedRangeModel model = jScrollBar.getModel();
295                     if (model.getExtent() + model.getValue() == model.getMaximum()) {
296                         ListTreeTableModelOnColumns model1 = null;
297                         Object modelObject = treeTables.getTree().getModel();
298                         if (modelObject instanceof ListTreeTableModelOnColumns) {
299                             model1 = (ListTreeTableModelOnColumns) modelObject;
300                             DefaultMutableTreeNode root1 = null;
301                             Object rootObject = model1.getRoot();
302                             if (rootObject instanceof DefaultMutableTreeNode) {
303                                 root1 = (DefaultMutableTreeNode) rootObject;
304                                 int index = allAgentDatas.indexOf(lastDataNode);
305                                 List<AgentHeapBean> list = listCopy(allAgentDatas, index, index + 20);
306                                 for (AgentHeapBean agentDataNode : list) {
307                                     DefaultMutableTreeNode defaultMutableTreeNode =
308                                         new DefaultMutableTreeNode(agentDataNode);
309                                     tableModelOnColumns
310                                         .insertNodeInto(defaultMutableTreeNode, root1, root1.getChildCount());
311                                     lastDataNode = agentDataNode;
312                                 }
313                             }
314                         }
315                     }
316                 }
317             }
318         };
319     }
320 
321     /**
322      * init treeTable Data
323      *
324      * @param sessionId long
325      * @param chartName String
326      * @return DefaultMutableTreeNode
327      */
328     public DefaultMutableTreeNode initData(long sessionId, String chartName) {
329         if (ProfilerLogManager.isInfoEnabled()) {
330             LOGGER.info("initData");
331         }
332         ChartStandard standard = ProfilerChartsView.sessionMap.get(sessionId).getPublisher().getStandard();
333         MemoryHeapManager memoryHeapManager = new MemoryHeapManager();
334         ChartDataRange selectedRang = standard.getSelectedRange(chartName);
335         String db = DataBaseApi.getInstance().checkTableRegister("ClassInfo");
336         if (selectedRang == null || StringUtils.isBlank(db)) {
337             return new DefaultMutableTreeNode();
338         }
339         long firstTime = standard.getFirstTimestamp();
340         long endTimeNew = firstTime + selectedRang.getEndTime();
341         allAgentDatas = memoryHeapManager.getMemoryHeapInfos(sessionId, 0L, endTimeNew);
342         AgentHeapBean agentHeapBean = new AgentHeapBean();
343         DefaultMutableTreeNode appNode = new DefaultMutableTreeNode();
344         int totalAllocations = 0;
345         int totalDeallocations = 0;
346         int totalTotalCount = 0;
347         long totalShallowSize = 0L;
348         if (!allAgentDatas.isEmpty()) {
349             for (int index = 0; index < MEMORY_AGENT_INIT_COUNT; index++) {
350                 AgentHeapBean node = allAgentDatas.get(index);
351                 if (index == MEMORY_AGENT_INIT_COUNT - 1) {
352                     lastDataNode = node;
353                 }
354                 appNode.add(new DefaultMutableTreeNode(node));
355             }
356         }
357         for (AgentHeapBean meInfo : allAgentDatas) {
358             totalAllocations = totalAllocations + meInfo.getAgentAllocationsCount();
359             totalDeallocations = totalDeallocations + meInfo.getAgentDeAllocationsCount();
360             totalTotalCount = totalTotalCount + meInfo.getAgentTotalInstanceCount();
361             totalShallowSize = totalShallowSize + meInfo.getAgentTotalshallowSize();
362         }
363         agentHeapBean.setAgentClazzName("app heap");
364         agentHeapBean.setAgentAllocationsCount(totalAllocations);
365         agentHeapBean.setAgentDeAllocationsCount(totalDeallocations);
366         agentHeapBean.setAgentTotalInstanceCount(totalTotalCount);
367         agentHeapBean.setAgentTotalshallowSize(totalShallowSize);
368         appNode.setUserObject(agentHeapBean);
369         return appNode;
370     }
371 
372     public ExpandTreeTable getTreeTable() {
373         return treeTable;
374     }
375 
376     public List<AgentHeapBean> getAllAgentDatas() {
377         return allAgentDatas;
378     }
379 
380     public void setAllAgentDatas(List<AgentHeapBean> allAgentDatas) {
381         this.allAgentDatas = allAgentDatas;
382     }
383 
384     public AgentHeapBean getLastDataNode() {
385         return lastDataNode;
386     }
387 
388     public void setLastDataNode(AgentHeapBean lastDataNode) {
389         this.lastDataNode = lastDataNode;
390     }
391 
392     public MouseMotionAdapter getMouseMotionAdapter() {
393         return mouseMotionAdapter;
394     }
395 
396     public void setMouseMotionAdapter(MouseMotionAdapter mouseMotionAdapter) {
397         this.mouseMotionAdapter = mouseMotionAdapter;
398     }
399 }
400