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.services.memory.nativeservice; 17 18 import ohos.devtools.services.memory.nativebean.NativeFrame; 19 import ohos.devtools.services.memory.nativebean.NativeInstanceObject; 20 import org.apache.commons.collections.map.MultiValueMap; 21 import org.apache.logging.log4j.LogManager; 22 import org.apache.logging.log4j.Logger; 23 24 import java.io.BufferedReader; 25 import java.io.File; 26 import java.io.FileInputStream; 27 import java.io.FileNotFoundException; 28 import java.io.IOException; 29 import java.io.InputStreamReader; 30 import java.util.Collection; 31 import java.util.HashMap; 32 import java.util.Iterator; 33 import java.util.Map; 34 35 /** 36 * NativeDataExternalInterface 37 * 38 * @since 2021/9/20 39 */ 40 public class NativeDataExternalInterface { 41 private static final Logger LOGGER = LogManager.getLogger(NativeDataExternalInterface.class); 42 43 private MultiValueMap nativeInstanceMap = new MultiValueMap(); 44 45 /** 46 * addr Function 47 */ 48 private Map<String, String> addrFunctionMap = new HashMap<>(); 49 50 /** 51 * addr, addrID 52 */ 53 private Map<String, String> addrMap = new HashMap<>(); 54 private boolean start = false; 55 56 /** 57 * parseNativeFile 58 * 59 * @param filePath filePath 60 */ parseNativeFile(String filePath)61 public void parseNativeFile(String filePath) { 62 File file = new File(filePath); 63 if (file == null || !file.isFile()) { 64 return; 65 } 66 FileInputStream inputStream = null; 67 BufferedReader bufferedReader = null; 68 try { 69 inputStream = new FileInputStream(file); 70 bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 71 executeParseFile(bufferedReader); 72 } catch (FileNotFoundException fileNotFoundException) { 73 LOGGER.error("FileNotFoundException ", fileNotFoundException); 74 } catch (IOException ioException) { 75 LOGGER.error("ioException ", ioException); 76 } finally { 77 if (inputStream != null) { 78 try { 79 inputStream.close(); 80 } catch (IOException ioException) { 81 ioException.printStackTrace(); 82 } 83 } 84 if (bufferedReader != null) { 85 try { 86 bufferedReader.close(); 87 } catch (IOException ioException) { 88 ioException.printStackTrace(); 89 } 90 } 91 } 92 } 93 executeParseFile(BufferedReader bufferedReader)94 private void executeParseFile(BufferedReader bufferedReader) throws IOException { 95 boolean isNeedNextLine = false; 96 boolean isSkip = false; 97 boolean startRecord = false; 98 String line = null; 99 NativeInstanceObject instance = null; 100 while ((line = bufferedReader.readLine()) != null) { 101 if ((!line.startsWith("malloc")) && (!start)) { 102 continue; 103 } 104 if (line.startsWith("malloc")) { 105 start = true; 106 instance = createInstance(line); 107 isNeedNextLine = true; 108 isSkip = false; 109 } 110 if ((!line.startsWith("malloc")) && (!line.startsWith("free")) && (!isSkip)) { 111 if (line.contains("malloc")) { 112 startRecord = true; 113 } 114 if (!startRecord) { 115 continue; 116 } 117 NativeFrame nativeFrame = createNativeFrame(line); 118 if (instance != null) { 119 instance.addNativeFrames(nativeFrame); 120 if (isNeedNextLine) { 121 instance.setFileName(nativeFrame.getFileName()); 122 instance.setFunctionName(nativeFrame.getFunctionName()); 123 addrFunctionMap.put(instance.getAddr(), instance.getFunctionName()); 124 isNeedNextLine = false; 125 if (!instance.isAdd()) { 126 nativeInstanceMap.put(instance.getFunctionName(), instance); 127 instance.setAdd(true); 128 } 129 } 130 } 131 } 132 if (line.startsWith("free")) { 133 startRecord = false; 134 String[] split = line.split(";"); 135 String freeAddr = split[3]; 136 String addrId = getAddrId(freeAddr); 137 String freeFunction = addrFunctionMap.get(addrId); 138 updateFreeInstance(freeAddr, freeFunction); 139 isSkip = true; 140 } 141 } 142 } 143 updateFreeInstance(String freeAddr, String freeFunction)144 private void updateFreeInstance(String freeAddr, String freeFunction) { 145 String addrId = getAddrId(freeAddr); 146 Collection collection = nativeInstanceMap.getCollection(freeFunction); 147 if (collection != null) { 148 Iterator iterator = collection.iterator(); 149 while (iterator.hasNext()) { 150 Object next = iterator.next(); 151 if (next instanceof NativeInstanceObject) { 152 NativeInstanceObject nativeInstance = (NativeInstanceObject) next; 153 if (addrId == String.valueOf(nativeInstance.getAddr())) { 154 nativeInstance.setDeAllocated(true); 155 } 156 } 157 } 158 } 159 } 160 getAddrId(String addr)161 private String getAddrId(String addr) { 162 return addrMap.get(addr); 163 } 164 updateAddrId(String addr)165 private String updateAddrId(String addr) { 166 String value = addr + System.nanoTime(); 167 addrMap.put(addr, value); 168 return value; 169 } 170 createInstance(String string)171 private NativeInstanceObject createInstance(String string) { 172 String[] split = string.split(";"); 173 String addr = split[3]; 174 String mallocSize = split[4]; 175 NativeInstanceObject nativeInstanceObject = new NativeInstanceObject(); 176 String addrId = updateAddrId(addr); 177 nativeInstanceObject.setAddr(addrId); 178 nativeInstanceObject.setSize(Long.parseLong(mallocSize)); 179 nativeInstanceObject.setInstanceCount(1); 180 return nativeInstanceObject; 181 } 182 createNativeFrame(String string)183 private NativeFrame createNativeFrame(String string) { 184 String[] split = string.split(";"); 185 String pc = split[0]; 186 if (split.length < 6) { 187 return new NativeFrame(pc, "", "", "", ""); 188 } 189 String functionName = split[2]; 190 String fileName = split[3]; 191 String offsetAddr = split[4]; 192 String line = split[5]; 193 return new NativeFrame(pc, fileName, functionName, offsetAddr, line); 194 } 195 getNativeInstanceMap()196 public MultiValueMap getNativeInstanceMap() { 197 return nativeInstanceMap; 198 } 199 } 200