Issue details
A short-circuit if (a || b) { ... } whose body is a shared block with two predecessors gets that block marked DUPLICATED (RegionMaker.java#L62-L64). When that block also holds a StringBuilder chain in the dex2jar/R8 idiom (the builder kept in a local and reloaded for each append, with the append return popped), the later string-concat simplification removes the now-redundant astore/aload/pop, and InsnRemover.remove emits Instruction removed from duplicated block: ..., please report this as an issue (InsnRemover.java#L224).
The decompiled output is correct; the warning is a false positive that tells users to report a bug. It shows only on .class input from dex2jar (R8 -> dex -> dex2jar), not on the original dex or on javac output, since only that path both shares the block (the ||) and reloads the builder through a local.
Sample
Java equivalent:
static String f(boolean a, boolean b, String s) {
if (a || b) {
s = s + ".mp4";
}
return s;
}
Minimal input, no Android tooling (Jasmin; .class/.jar build with dex2jar's bundled d2j-jasmin2jar.sh):
.method public static f(ZZLjava/lang/String;)Ljava/lang/String;
iload 0
ifne L0 ; a -> L0
aload 2
astore 3
iload 1
ifeq L1 ; !b -> skip
L0: ; shared block, two predecessors
new java/lang/StringBuilder
dup
invokespecial java/lang/StringBuilder/<init>()V
astore 3 ; builder in a local (dex2jar idiom)
aload 3
aload 2
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
pop
aload 3
ldc ".mp4"
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
pop
aload 3
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
astore 3
L1:
aload 3
areturn
.limit locals 4
.limit stack 2
.end method
Output on master (8c28a85), correct code with two spurious warnings:
/* JADX WARN: Code duplicated, block: B:6:0x000a */
/* JADX WARN: Instruction removed from duplicated block: B:6:0x000a, please report this as an issue */
public static String f(boolean z, boolean z2, String str) {
String str2;
if (z) {
str2 = str + ".mp4";
} else {
str2 = str;
if (z2) {
str2 = str + ".mp4";
}
}
return str2;
}
Found in a public app: com.rubenmayayo.reddit (Boost for Reddit) 1.12.12, method rb.FileCacheManager.getFileNameFromUrl (after running the APK through dex2jar).
Jadx version
master 8c28a85 (current HEAD)
Issue details
A short-circuit
if (a || b) { ... }whose body is a shared block with two predecessors gets that block markedDUPLICATED(RegionMaker.java#L62-L64). When that block also holds aStringBuilderchain in the dex2jar/R8 idiom (the builder kept in a local and reloaded for eachappend, with theappendreturnpopped), the later string-concat simplification removes the now-redundantastore/aload/pop, andInsnRemover.removeemitsInstruction removed from duplicated block: ..., please report this as an issue(InsnRemover.java#L224).The decompiled output is correct; the warning is a false positive that tells users to report a bug. It shows only on
.classinput from dex2jar (R8 -> dex -> dex2jar), not on the original dex or on javac output, since only that path both shares the block (the||) and reloads the builder through a local.Sample
Java equivalent:
Minimal input, no Android tooling (Jasmin;
.class/.jarbuild with dex2jar's bundledd2j-jasmin2jar.sh):Output on master (
8c28a85), correct code with two spurious warnings:Found in a public app:
com.rubenmayayo.reddit(Boost for Reddit) 1.12.12, methodrb.FileCacheManager.getFileNameFromUrl(after running the APK through dex2jar).Jadx version
master
8c28a85(current HEAD)