core: fix processing same class several times (#274)
Caution: This change can increase memory usage! However overall decompilation must be faster
This commit is contained in:
@@ -197,8 +197,12 @@ public final class JadxDecompiler {
|
||||
continue;
|
||||
}
|
||||
executor.execute(() -> {
|
||||
cls.decompile();
|
||||
SaveCode.save(outDir, args, cls.getClassNode());
|
||||
try {
|
||||
cls.decompile();
|
||||
SaveCode.save(outDir, args, cls.getClassNode());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error saving class: {}", cls.getFullName(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,10 @@ public final class JavaClass implements JavaNode {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void unload() {
|
||||
cls.unload();
|
||||
}
|
||||
|
||||
ClassNode getClassNode() {
|
||||
return cls;
|
||||
}
|
||||
@@ -107,12 +111,7 @@ public final class JavaClass implements JavaNode {
|
||||
rootDecompiler.getMethodsMap().put(m, javaMethod);
|
||||
}
|
||||
}
|
||||
Collections.sort(mths, new Comparator<JavaMethod>() {
|
||||
@Override
|
||||
public int compare(JavaMethod o1, JavaMethod o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
mths.sort(Comparator.comparing(JavaMethod::getName));
|
||||
this.methods = Collections.unmodifiableList(mths);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,9 @@ import jadx.core.dex.visitors.DepthTraversal;
|
||||
import jadx.core.dex.visitors.IDexTreeVisitor;
|
||||
import jadx.core.utils.ErrorsCounter;
|
||||
|
||||
import static jadx.core.dex.nodes.ProcessState.GENERATED;
|
||||
import static jadx.core.dex.nodes.ProcessState.NOT_LOADED;
|
||||
import static jadx.core.dex.nodes.ProcessState.PROCESSED;
|
||||
import static jadx.core.dex.nodes.ProcessState.STARTED;
|
||||
import static jadx.core.dex.nodes.ProcessState.UNLOADED;
|
||||
|
||||
public final class ProcessClass {
|
||||
|
||||
@@ -38,15 +36,9 @@ public final class ProcessClass {
|
||||
if (cls.getState() == PROCESSED && codeGen != null) {
|
||||
processDependencies(cls, passes);
|
||||
codeGen.visit(cls);
|
||||
cls.setState(GENERATED);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ErrorsCounter.classError(cls, e.getClass().getSimpleName(), e);
|
||||
} finally {
|
||||
if (cls.getState() == GENERATED) {
|
||||
cls.unload();
|
||||
cls.setState(UNLOADED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package jadx.core.codegen;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.visitors.AbstractVisitor;
|
||||
import jadx.core.utils.exceptions.CodegenException;
|
||||
|
||||
public class CodeGen extends AbstractVisitor {
|
||||
public class CodeGen {
|
||||
|
||||
@Override
|
||||
public boolean visit(ClassNode cls) throws CodegenException {
|
||||
ClassGen clsGen = new ClassGen(cls, cls.root().getArgs());
|
||||
CodeWriter clsCode = clsGen.makeClass();
|
||||
|
||||
@@ -39,6 +39,8 @@ import jadx.core.dex.nodes.parser.StaticValuesParser;
|
||||
import jadx.core.utils.exceptions.DecodeException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.dex.nodes.ProcessState.UNLOADED;
|
||||
|
||||
public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class);
|
||||
|
||||
@@ -264,6 +266,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
|
||||
for (ClassNode innerCls : getInnerClasses()) {
|
||||
innerCls.unload();
|
||||
}
|
||||
setState(UNLOADED);
|
||||
}
|
||||
|
||||
private void buildCache() {
|
||||
|
||||
@@ -403,8 +403,8 @@ public class MethodNode extends LineAttrNode implements ILoadable, IDexNode {
|
||||
}
|
||||
|
||||
public void finishBasicBlocks() {
|
||||
((ArrayList<BlockNode>) blocks).trimToSize();
|
||||
((ArrayList<BlockNode>) exitBlocks).trimToSize();
|
||||
trimList(blocks);
|
||||
trimList(exitBlocks);
|
||||
|
||||
blocks = Collections.unmodifiableList(blocks);
|
||||
exitBlocks = Collections.unmodifiableList(exitBlocks);
|
||||
@@ -414,6 +414,12 @@ public class MethodNode extends LineAttrNode implements ILoadable, IDexNode {
|
||||
}
|
||||
}
|
||||
|
||||
private void trimList(List<BlockNode> blocks) {
|
||||
if (blocks instanceof ArrayList) {
|
||||
((ArrayList<BlockNode>)blocks).trimToSize();
|
||||
}
|
||||
}
|
||||
|
||||
public List<BlockNode> getBasicBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import jadx.api.JadxArgs;
|
||||
import jadx.core.codegen.CodeWriter;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
public class SaveCode {
|
||||
|
||||
@@ -16,6 +17,9 @@ public class SaveCode {
|
||||
return;
|
||||
}
|
||||
CodeWriter clsCode = cls.getCode();
|
||||
if (clsCode == null) {
|
||||
throw new JadxRuntimeException("Code not generated for class " + cls.getFullName());
|
||||
}
|
||||
String fileName = cls.getClassInfo().getFullPath() + ".java";
|
||||
if (args.isFallbackMode()) {
|
||||
fileName += ".jadx";
|
||||
|
||||
@@ -52,6 +52,8 @@ public class JadxWrapper {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
progressMonitor.close();
|
||||
LOG.info("decompilation complete, freeing memory ...");
|
||||
decompiler.getClasses().forEach(JavaClass::unload);
|
||||
LOG.info("done");
|
||||
} catch (InterruptedException e) {
|
||||
LOG.error("Save interrupted", e);
|
||||
|
||||
@@ -51,6 +51,7 @@ public class JClass extends JLoadableNode {
|
||||
public synchronized void load() {
|
||||
if (!loaded) {
|
||||
cls.decompile();
|
||||
cls.unload();
|
||||
loaded = true;
|
||||
}
|
||||
update();
|
||||
|
||||
Reference in New Issue
Block a user