未验证 提交 15c9d333 编写于 作者: S Skylot

fix(gui): handle possible classes overlap in disk cache (#1633)

上级 7e0fafba
......@@ -13,6 +13,7 @@ import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Comparator;
......@@ -228,7 +229,8 @@ public class FileUtils {
public static void writeFile(Path file, String data) throws IOException {
FileUtils.makeDirsForFile(file);
Files.write(file, data.getBytes(StandardCharsets.UTF_8));
Files.write(file, data.getBytes(StandardCharsets.UTF_8),
StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
}
public static String readFile(Path textFile) throws IOException {
......
......@@ -15,6 +15,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
......@@ -30,6 +31,7 @@ import jadx.api.ICodeCache;
import jadx.api.ICodeInfo;
import jadx.api.JadxArgs;
import jadx.core.Jadx;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -42,7 +44,7 @@ import static java.nio.file.StandardOpenOption.WRITE;
public class DiskCodeCache implements ICodeCache {
private static final Logger LOG = LoggerFactory.getLogger(DiskCodeCache.class);
private static final int DATA_FORMAT_VERSION = 12;
private static final int DATA_FORMAT_VERSION = 13;
private static final byte[] JADX_NAMES_MAP_HEADER = "jadxnm".getBytes(StandardCharsets.US_ASCII);
......@@ -55,6 +57,7 @@ public class DiskCodeCache implements ICodeCache {
private final ExecutorService writePool;
private final Map<String, ICodeInfo> writeOps = new ConcurrentHashMap<>();
private final Map<String, Integer> namesMap = new ConcurrentHashMap<>();
private final Map<String, Integer> allClsIds;
public DiskCodeCache(RootNode root, Path baseDir) {
srcDir = baseDir.resolve("sources");
......@@ -65,6 +68,7 @@ public class DiskCodeCache implements ICodeCache {
codeVersion = buildCodeVersion(args);
writePool = Executors.newFixedThreadPool(args.getThreadsCount());
codeMetadataAdapter = new CodeMetadataAdapter(root);
allClsIds = buildClassIdsMap(root.getClasses());
if (checkCodeVersion()) {
loadNamesMap();
} else {
......@@ -112,6 +116,7 @@ public class DiskCodeCache implements ICodeCache {
public void add(String clsFullName, ICodeInfo codeInfo) {
writeOps.put(clsFullName, codeInfo);
int clsId = getClsId(clsFullName);
namesMap.put(clsFullName, clsId);
writePool.execute(() -> {
try {
FileUtils.writeFile(getJavaFile(clsId), codeInfo.getCodeStr());
......@@ -218,7 +223,11 @@ public class DiskCodeCache implements ICodeCache {
}
private int getClsId(String clsFullName) {
return namesMap.computeIfAbsent(clsFullName, n -> namesMap.size());
Integer id = allClsIds.get(clsFullName);
if (id == null) {
throw new JadxRuntimeException("Unknown class name: " + clsFullName);
}
return id;
}
private void saveNamesMap() {
......@@ -250,6 +259,13 @@ public class DiskCodeCache implements ICodeCache {
String clsName = in.readUTF();
int clsId = in.readInt();
namesMap.put(clsName, clsId);
Integer prevId = allClsIds.get(clsName);
if (prevId == null || prevId != clsId) {
LOG.debug("Unexpected class id, got: {}, expect: {}", clsId, prevId);
LOG.warn("Inconsistent disk cache, resetting...");
reset();
return;
}
}
LOG.info("Found {} classes in disk cache, dir: {}", count, metaDir.getParent());
} catch (Exception e) {
......@@ -271,6 +287,16 @@ public class DiskCodeCache implements ICodeCache {
return Paths.get(firstByte, FileUtils.intToHex(clsId) + ext);
}
private Map<String, Integer> buildClassIdsMap(List<ClassNode> classes) {
int clsCount = classes.size();
Map<String, Integer> map = new HashMap<>(clsCount);
for (int i = 0; i < clsCount; i++) {
ClassNode cls = classes.get(i);
map.put(cls.getRawName(), i);
}
return map;
}
@SuppressWarnings("ResultOfMethodCallIgnored")
@Override
public void close() throws IOException {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册