From 068234f0cab197a476cba5b30592aa4d88c50249 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 29 Jul 2019 14:55:50 +0300 Subject: [PATCH] fix: remove synchronization lock for code generation (#726) --- .../src/main/java/jadx/api/JavaClass.java | 19 ++++--- .../src/main/java/jadx/core/ProcessClass.java | 50 +++++++------------ 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/jadx-core/src/main/java/jadx/api/JavaClass.java b/jadx-core/src/main/java/jadx/api/JavaClass.java index ad08fbbd7d1..2e7d3b99812 100644 --- a/jadx-core/src/main/java/jadx/api/JavaClass.java +++ b/jadx-core/src/main/java/jadx/api/JavaClass.java @@ -25,6 +25,7 @@ public final class JavaClass implements JavaNode { private List innerClasses = Collections.emptyList(); private List fields = Collections.emptyList(); private List methods = Collections.emptyList(); + private boolean listsLoaded; JavaClass(ClassNode classNode, JadxDecompiler decompiler) { this.decompiler = decompiler; @@ -59,7 +60,6 @@ public synchronized void decompile() { } if (cls.getCode() == null) { cls.decompile(); - load(); } } @@ -75,13 +75,20 @@ public synchronized String getSmali() { public synchronized void unload() { cls.unload(); + listsLoaded = false; } public ClassNode getClassNode() { return cls; } - private void load() { + private void loadLists() { + if (listsLoaded) { + return; + } + listsLoaded = true; + decompile(); + JadxDecompiler rootDecompiler = getRootDecompiler(); int inClsCount = cls.getInnerClasses().size(); if (inClsCount != 0) { @@ -89,7 +96,7 @@ private void load() { for (ClassNode inner : cls.getInnerClasses()) { if (!inner.contains(AFlag.DONT_GENERATE)) { JavaClass javaClass = new JavaClass(inner, this); - javaClass.load(); + javaClass.loadLists(); list.add(javaClass); rootDecompiler.getClassesMap().put(inner, javaClass); } @@ -205,17 +212,17 @@ public AccessInfo getAccessInfo() { } public List getInnerClasses() { - decompile(); + loadLists(); return innerClasses; } public List getFields() { - decompile(); + loadLists(); return fields; } public List getMethods() { - decompile(); + loadLists(); return methods; } diff --git a/jadx-core/src/main/java/jadx/core/ProcessClass.java b/jadx-core/src/main/java/jadx/core/ProcessClass.java index cee18a6dacd..b639042f276 100644 --- a/jadx-core/src/main/java/jadx/core/ProcessClass.java +++ b/jadx-core/src/main/java/jadx/core/ProcessClass.java @@ -5,7 +5,6 @@ import jadx.api.ICodeInfo; import jadx.core.codegen.CodeGen; import jadx.core.dex.nodes.ClassNode; -import jadx.core.dex.nodes.ProcessState; import jadx.core.dex.visitors.DepthTraversal; import jadx.core.dex.visitors.IDexTreeVisitor; import jadx.core.utils.ErrorsCounter; @@ -22,28 +21,16 @@ private ProcessClass() { } public static void process(ClassNode cls) { - process(cls, false); - } - - @NotNull - public static ICodeInfo generateCode(ClassNode cls) { - ICodeInfo codeInfo = process(cls, true); - if (codeInfo == null) { - throw new JadxRuntimeException("Failed to generate code for class: " + cls.getFullName()); - } - return codeInfo; - } - - private static ICodeInfo process(ClassNode cls, boolean generateCode) { ClassNode topParentClass = cls.getTopParentClass(); if (topParentClass != cls) { - return process(topParentClass, generateCode); + process(topParentClass); + return; } - if (!generateCode && cls.getState() == PROCESS_COMPLETE) { + if (cls.getState() == PROCESS_COMPLETE) { // nothing to do - return null; + return; } - synchronized (getSyncObj(cls)) { + synchronized (cls.getClassInfo()) { try { if (cls.getState() == NOT_LOADED) { cls.load(); @@ -55,27 +42,26 @@ private static ICodeInfo process(ClassNode cls, boolean generateCode) { } cls.setState(PROCESS_COMPLETE); } - if (generateCode && cls.getState() == PROCESS_COMPLETE) { - processDependencies(cls); - ICodeInfo code = CodeGen.generate(cls); - cls.setState(ProcessState.GENERATED); - // TODO: unload class (need to build dependency tree or allow to load class several times) - return code; - } } catch (Throwable e) { ErrorsCounter.classError(cls, e.getClass().getSimpleName(), e); } } - return null; } - private static Object getSyncObj(ClassNode cls) { - return cls.getClassInfo(); - } + @NotNull + public static ICodeInfo generateCode(ClassNode cls) { + ClassNode topParentClass = cls.getTopParentClass(); + if (topParentClass != cls) { + return generateCode(topParentClass); + } + try { + process(cls); + cls.getDependencies().forEach(ProcessClass::process); - private static void processDependencies(ClassNode cls) { - for (ClassNode depCls : cls.getDependencies()) { - process(depCls, false); + // TODO: unload class (need to build dependency tree or allow to load class several times) + return CodeGen.generate(cls); + } catch (Throwable e) { + throw new JadxRuntimeException("Failed to generate code for class: " + cls.getFullName(), e); } } }