* Added failing test for super member shadowing.
* Fixed new test containing incorrect variable names.
* Implemented marking super fields used in a subclass with super keyword.
* Renamed member variable in the example to reflect smali and test.
* Fixed formatting and imports.
Exception in thread "pool-9-thread-7" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1445)
at java.util.HashMap$EntryIterator.next(HashMap.java:1479)
at java.util.HashMap$EntryIterator.next(HashMap.java:1477)
at jadx.core.dex.info.ConstStorage$ValueStorage.removeForCls(ConstStorage.java:61)
at jadx.core.dex.info.ConstStorage.removeForClass(ConstStorage.java:100)
at jadx.core.dex.nodes.ClassNode.deepUnload(ClassNode.java:290)
at jadx.core.dex.nodes.ClassNode.deepUnload(ClassNode.java:295)
at jadx.core.dex.nodes.ClassNode.reloadCode(ClassNode.java:284)
at jadx.api.JavaClass.refresh(JavaClass.java:62)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
If the constant already got duplicates - it will have duplicates even after
class reload, won't it?
But removing this constant from duplicates may break constants replacing
(just imagine a class TestClass with public static final int TEST_CONSTANT = 1;
- after reloading TestClass each "(int) 1" litheral will be replaced to
"TEST_CONSTANT" reference in each reloaded class and trivial increments will
become werid expressions (int y = x + 1; will become
int y = x + TestClass.TEST_CONSTANT;)).
This is a microoptimization, which remove unnecessary values.put() and
values.remove() pair of operations if ValueStorage.put() is called for a
known duplicated value.
This may happen because MethodNode.unloadInsnArr() call from BlockSplitter.visit() - after it instructions[] become null.
So, try to reload method before processing its instructions array and bail if insnArr still null even after reloading method.
There is a duplicate control in the ConstStorage.ValueStorage.add() method,
so each constant should be added only once, and not be added on class refresh.
Fixes "Replace constants" failure after renaming any node.
checkInstructions() may fail with NPE:
ERROR - NullPointerException in pass: BlockSplitter in method: com.google.common.primitives.Ints.IntArrayAsList.<init>(int[], int, int):void, dex: out.dex
java.lang.NullPointerException: null
at jadx.core.dex.nodes.MethodNode.checkInstructions(MethodNode.java:159)
at jadx.core.dex.visitors.blocksmaker.BlockSplitter.visit(BlockSplitter.java:49)
at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:31)
at jadx.core.dex.visitors.DepthTraversal.lambda$visit$1(DepthTraversal.java:16)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:16)
at jadx.core.dex.visitors.DepthTraversal.lambda$visit$0(DepthTraversal.java:15)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at jadx.core.dex.visitors.DepthTraversal.visit(DepthTraversal.java:15)
at jadx.core.ProcessClass.process(ProcessClass.java:41)
at jadx.core.ProcessClass.generateCode(ProcessClass.java:58)
at jadx.core.dex.nodes.ClassNode.decompile(ClassNode.java:292)
at jadx.core.dex.nodes.ClassNode.decompile(ClassNode.java:271)
at jadx.core.dex.nodes.ClassNode.refresh(ClassNode.java:303)
at jadx.api.JavaClass.refresh(JavaClass.java:61)
at jadx.gui.treemodel.JClass.refresh(JClass.java:63)
...
This happens because MethodNode.unloadInsnArr() call from BlockSplitter.visit() - after it instructions[] become null.
So, try to reload method before processing its instructions array.