Skip to content

Commit

Permalink
fix: remove synchronization lock for code generation (#726)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jul 29, 2019
1 parent ccb8ed1 commit 068234f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 38 deletions.
19 changes: 13 additions & 6 deletions jadx-core/src/main/java/jadx/api/JavaClass.java
Expand Up @@ -25,6 +25,7 @@ public final class JavaClass implements JavaNode {
private List<JavaClass> innerClasses = Collections.emptyList();
private List<JavaField> fields = Collections.emptyList();
private List<JavaMethod> methods = Collections.emptyList();
private boolean listsLoaded;

JavaClass(ClassNode classNode, JadxDecompiler decompiler) {
this.decompiler = decompiler;
Expand Down Expand Up @@ -59,7 +60,6 @@ public synchronized void decompile() {
}
if (cls.getCode() == null) {
cls.decompile();
load();
}
}

Expand All @@ -75,21 +75,28 @@ 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) {
List<JavaClass> list = new ArrayList<>(inClsCount);
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);
}
Expand Down Expand Up @@ -205,17 +212,17 @@ public AccessInfo getAccessInfo() {
}

public List<JavaClass> getInnerClasses() {
decompile();
loadLists();
return innerClasses;
}

public List<JavaField> getFields() {
decompile();
loadLists();
return fields;
}

public List<JavaMethod> getMethods() {
decompile();
loadLists();
return methods;
}

Expand Down
50 changes: 18 additions & 32 deletions jadx-core/src/main/java/jadx/core/ProcessClass.java
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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);
}
}
}

0 comments on commit 068234f

Please sign in to comment.