From 1c6e51f8b2c6f7bbfd21c027bc8558f53cdfd908 Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 13 Dec 2019 18:19:12 +0000 Subject: [PATCH] fix: allow to regenerate class code (#791) --- .../java/jadx/core/dex/nodes/ClassNode.java | 30 +++++++++----- .../jadx/core/dex/nodes/ProcessState.java | 6 +-- .../api/utils/assertj/JadxCodeAssertions.java | 7 ++++ .../integration/others/TestClassReGen.java | 41 +++++++++++++++++++ 4 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/others/TestClassReGen.java diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java index 03a6ea94a..87f505c6f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java @@ -40,7 +40,7 @@ import jadx.core.utils.exceptions.DecodeException; import jadx.core.utils.exceptions.JadxRuntimeException; import static jadx.core.dex.nodes.ProcessState.LOADED; -import static jadx.core.dex.nodes.ProcessState.UNLOADED; +import static jadx.core.dex.nodes.ProcessState.NOT_LOADED; public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class); @@ -262,23 +262,33 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { } } - public synchronized ICodeInfo decompile() { + public ICodeInfo decompile() { + return decompile(true); + } + + public ICodeInfo getCode() { + return decompile(true); + } + + public ICodeInfo reloadCode() { + return decompile(false); + } + + private synchronized ICodeInfo decompile(boolean searchInCache) { ICodeCache codeCache = root().getCodeCache(); ClassNode topParentClass = getTopParentClass(); String clsRawName = topParentClass.getRawName(); - ICodeInfo code = codeCache.get(clsRawName); - if (code != null) { - return code; + if (searchInCache) { + ICodeInfo code = codeCache.get(clsRawName); + if (code != null) { + return code; + } } ICodeInfo codeInfo = ProcessClass.generateCode(topParentClass); codeCache.add(clsRawName, codeInfo); return codeInfo; } - public ICodeInfo getCode() { - return decompile(); - } - @Override public void load() { for (MethodNode mth : getMethods()) { @@ -300,7 +310,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { innerClasses.forEach(ClassNode::unload); fields.forEach(FieldNode::unloadAttributes); unloadAttributes(); - setState(UNLOADED); + setState(NOT_LOADED); } private void buildCache() { diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ProcessState.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ProcessState.java index db02f08f3..4cce135b8 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/ProcessState.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ProcessState.java @@ -4,15 +4,13 @@ public enum ProcessState { NOT_LOADED, LOADED, PROCESS_STARTED, - PROCESS_COMPLETE, - GENERATED, - UNLOADED; + PROCESS_COMPLETE; public boolean isLoaded() { return this != NOT_LOADED; } public boolean isProcessed() { - return this == PROCESS_COMPLETE || this == GENERATED || this == UNLOADED; + return this == PROCESS_COMPLETE; } } diff --git a/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java b/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java index 67836f63b..c933a09ca 100644 --- a/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java +++ b/jadx-core/src/test/java/jadx/tests/api/utils/assertj/JadxCodeAssertions.java @@ -51,4 +51,11 @@ public class JadxCodeAssertions extends AbstractStringAssert } return countString(1, sb.toString()); } + + public JadxCodeAssertions print() { + System.out.println("-----------------------------------------------------------"); + System.out.println(actual); + System.out.println("-----------------------------------------------------------"); + return this; + } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/others/TestClassReGen.java b/jadx-core/src/test/java/jadx/tests/integration/others/TestClassReGen.java new file mode 100644 index 000000000..29a743d42 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/others/TestClassReGen.java @@ -0,0 +1,41 @@ +package jadx.tests.integration.others; + +import org.junit.jupiter.api.Test; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestClassReGen extends IntegrationTest { + + public static class TestCls { + private int intField = 5; + + public static class A { + } + + public int test() { + return 0; + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + assertThat(cls.getCode()) + .containsOnlyOnce("private int intField = 5;") + .containsOnlyOnce("public static class A {") + .containsOnlyOnce("public int test() {"); + + cls.getInnerClasses().get(0).getClassInfo().changeShortName("ARenamed"); + cls.searchMethodByShortName("test").getMethodInfo().setAlias("testRenamed"); + cls.searchFieldByName("intField").getFieldInfo().setAlias("intFieldRenamed"); + + assertThat(cls.reloadCode()) + .print() + .containsOnlyOnce("private int intFieldRenamed = 5;") + .containsOnlyOnce("public static class ARenamed {") + .containsOnlyOnce("public int testRenamed() {"); + } +}