未验证 提交 9ba07b98 编写于 作者: S Skylot

fix(gui): reduce usage of nullable decompiler field in jadx wrapper (#1506)

上级 e6b6b93c
......@@ -6,18 +6,27 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeInfo;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JavaNode;
import jadx.api.JavaPackage;
import jadx.api.ResourceFile;
import jadx.api.impl.InMemoryCodeCache;
import jadx.api.metadata.ICodeNodeRef;
import jadx.api.plugins.JadxPlugin;
import jadx.api.plugins.JadxPluginManager;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.ProcessState;
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.rename.RenameVisitor;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.utils.files.FileUtils;
import jadx.gui.settings.JadxProject;
import jadx.gui.settings.JadxSettings;
......@@ -34,7 +43,7 @@ public class JadxWrapper {
private static final Logger LOG = LoggerFactory.getLogger(JadxWrapper.class);
private final MainWindow mainWindow;
private JadxDecompiler decompiler;
private @Nullable JadxDecompiler decompiler;
public JadxWrapper(MainWindow mainWindow) {
this.mainWindow = mainWindow;
......@@ -52,14 +61,14 @@ public class JadxWrapper {
this.decompiler.load();
initCodeCache();
} catch (Exception e) {
LOG.error("Jadx init error", e);
LOG.error("Jadx decompiler wrapper init error", e);
close();
}
}
// TODO: check and move into core package
public void unloadClasses() {
for (ClassNode cls : decompiler.getRoot().getClasses()) {
for (ClassNode cls : getDecompiler().getRoot().getClasses()) {
ProcessState clsState = cls.getState();
cls.unload();
cls.setState(clsState == PROCESS_COMPLETE ? GENERATED_AND_UNLOADED : NOT_LOADED);
......@@ -70,12 +79,12 @@ public class JadxWrapper {
try {
if (decompiler != null) {
decompiler.close();
mainWindow.getCacheObject().reset();
}
} catch (Exception e) {
LOG.error("Jadx decompiler close error", e);
} finally {
decompiler = null;
mainWindow.getCacheObject().reset();
}
}
......@@ -94,7 +103,7 @@ public class JadxWrapper {
}
private BufferCodeCache buildBufferedDiskCache() {
DiskCodeCache diskCache = new DiskCodeCache(decompiler.getRoot(), getProject().getCacheDir());
DiskCodeCache diskCache = new DiskCodeCache(getDecompiler().getRoot(), getProject().getCacheDir());
return new BufferCodeCache(diskCache);
}
......@@ -102,14 +111,14 @@ public class JadxWrapper {
* Get the complete list of classes
*/
public List<JavaClass> getClasses() {
return decompiler.getClasses();
return getDecompiler().getClasses();
}
/**
* Get all classes that are not excluded by the excluded packages settings
*/
public List<JavaClass> getIncludedClasses() {
List<JavaClass> classList = decompiler.getClasses();
List<JavaClass> classList = getDecompiler().getClasses();
List<String> excludedPackages = getExcludedPackages();
if (excludedPackages.isEmpty()) {
return classList;
......@@ -123,7 +132,7 @@ public class JadxWrapper {
* Get all classes that are not excluded by the excluded packages settings including inner classes
*/
public List<JavaClass> getIncludedClassesWithInners() {
List<JavaClass> classes = decompiler.getClassesWithInners();
List<JavaClass> classes = getDecompiler().getClassesWithInners();
List<String> excludedPackages = getExcludedPackages();
if (excludedPackages.isEmpty()) {
return classes;
......@@ -145,7 +154,7 @@ public class JadxWrapper {
}
public List<List<JavaClass>> buildDecompileBatches(List<JavaClass> classes) {
return decompiler.getDecompileScheduler().buildBatches(classes);
return getDecompiler().getDecompileScheduler().buildBatches(classes);
}
// TODO: move to CLI and filter classes in JadxDecompiler
......@@ -175,20 +184,61 @@ public class JadxWrapper {
getSettings().sync();
}
public List<JavaPackage> getPackages() {
return decompiler.getPackages();
public List<JadxPlugin> getAllPlugins() {
if (decompiler != null) {
return decompiler.getPluginManager().getAllPlugins();
}
JadxPluginManager pluginManager = new JadxPluginManager();
pluginManager.load();
return pluginManager.getAllPlugins();
}
public List<ResourceFile> getResources() {
return decompiler.getResources();
/**
* TODO: make method private
* Do not store JadxDecompiler in fields to not leak old instances
*/
public @NotNull JadxDecompiler getDecompiler() {
if (decompiler == null || decompiler.getRoot() == null) {
throw new JadxRuntimeException("Decompiler not yet loaded");
}
return decompiler;
}
public JadxDecompiler getDecompiler() {
return decompiler;
// TODO: forbid usage of this method
public RootNode getRootNode() {
return getDecompiler().getRoot();
}
public void reInitRenameVisitor() {
new RenameVisitor().init(getRootNode());
}
public void reloadCodeData() {
getDecompiler().reloadCodeData();
}
public JavaNode getJavaNodeByRef(ICodeNodeRef nodeRef) {
return getDecompiler().getJavaNodeByRef(nodeRef);
}
public JavaNode getEnclosingNode(ICodeInfo codeInfo, int pos) {
return getDecompiler().getEnclosingNode(codeInfo, pos);
}
public List<Runnable> getSaveTasks() {
return getDecompiler().getSaveTasks();
}
public List<JavaPackage> getPackages() {
return getDecompiler().getPackages();
}
public List<ResourceFile> getResources() {
return getDecompiler().getResources();
}
public JadxArgs getArgs() {
return decompiler.getArgs();
return getDecompiler().getArgs();
}
public JadxProject getProject() {
......@@ -204,14 +254,14 @@ public class JadxWrapper {
* Full name of an outer class. Inner classes are not supported.
*/
public @Nullable JavaClass searchJavaClassByFullAlias(String fullName) {
return decompiler.getClasses().stream()
return getDecompiler().getClasses().stream()
.filter(cls -> cls.getFullName().equals(fullName))
.findFirst()
.orElse(null);
}
public @Nullable JavaClass searchJavaClassByOrigClassName(String fullName) {
return decompiler.searchJavaClassByOrigFullName(fullName);
return getDecompiler().searchJavaClassByOrigFullName(fullName);
}
/**
......@@ -219,7 +269,7 @@ public class JadxWrapper {
* Full raw name of an outer class. Inner classes are not supported.
*/
public @Nullable JavaClass searchJavaClassByRawName(String rawName) {
return decompiler.getClasses().stream()
return getDecompiler().getClasses().stream()
.filter(cls -> cls.getRawName().equals(rawName))
.findFirst()
.orElse(null);
......
......@@ -160,7 +160,7 @@ public class DbgUtils {
// TODO: parse AndroidManifest.xml instead of looking for keywords
private static String getManifestContent(MainWindow mainWindow) {
try {
ResourceFile androidManifest = mainWindow.getWrapper().getDecompiler().getResources()
ResourceFile androidManifest = mainWindow.getWrapper().getResources()
.stream()
.filter(res -> res.getType() == ResourceType.MANIFEST)
.findFirst()
......
......@@ -6,7 +6,6 @@ import java.util.List;
import javax.swing.JOptionPane;
import jadx.api.ICodeCache;
import jadx.api.JadxDecompiler;
import jadx.gui.JadxWrapper;
import jadx.gui.ui.MainWindow;
import jadx.gui.utils.NLS;
......@@ -35,9 +34,8 @@ public class ExportTask extends CancelableBackgroundTask {
@Override
public List<Runnable> scheduleJobs() {
wrapCodeCache();
JadxDecompiler decompiler = wrapper.getDecompiler();
decompiler.getArgs().setRootDir(saveDir);
List<Runnable> saveTasks = decompiler.getSaveTasks();
wrapper.getArgs().setRootDir(saveDir);
List<Runnable> saveTasks = wrapper.getSaveTasks();
this.timeLimit = DecompileTask.calcDecompileTimeLimit(saveTasks.size());
return saveTasks;
}
......
......@@ -8,11 +8,11 @@ import org.slf4j.LoggerFactory;
import jadx.api.ICodeCache;
import jadx.api.ICodeWriter;
import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JavaNode;
import jadx.api.metadata.ICodeMetadata;
import jadx.api.metadata.ICodeNodeRef;
import jadx.gui.JadxWrapper;
import jadx.gui.jobs.Cancelable;
import jadx.gui.search.SearchSettings;
import jadx.gui.treemodel.CodeNode;
......@@ -23,7 +23,7 @@ public final class CodeSearchProvider extends BaseSearchProvider {
private static final Logger LOG = LoggerFactory.getLogger(CodeSearchProvider.class);
private final ICodeCache codeCache;
private final JadxDecompiler decompiler;
private final JadxWrapper wrapper;
private @Nullable String code;
private int clsNum = 0;
......@@ -32,7 +32,7 @@ public final class CodeSearchProvider extends BaseSearchProvider {
public CodeSearchProvider(MainWindow mw, SearchSettings searchSettings, List<JavaClass> classes) {
super(mw, searchSettings, classes);
this.codeCache = mw.getWrapper().getArgs().getCodeCache();
this.decompiler = mw.getWrapper().getDecompiler();
this.wrapper = mw.getWrapper();
}
@Override
......@@ -75,7 +75,7 @@ public final class CodeSearchProvider extends BaseSearchProvider {
try {
ICodeMetadata metadata = javaCls.getCodeInfo().getCodeMetadata();
ICodeNodeRef nodeRef = metadata.getNodeAt(pos);
JavaNode encNode = decompiler.getJavaNodeByRef(nodeRef);
JavaNode encNode = wrapper.getJavaNodeByRef(nodeRef);
if (encNode != null) {
return convert(encNode);
}
......
......@@ -65,7 +65,6 @@ import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.api.plugins.JadxPlugin;
import jadx.api.plugins.JadxPluginInfo;
import jadx.api.plugins.JadxPluginManager;
import jadx.api.plugins.options.JadxPluginOptions;
import jadx.api.plugins.options.OptionDescription;
import jadx.gui.ui.MainWindow;
......@@ -580,8 +579,7 @@ public class JadxSettingsWindow extends JDialog {
private SettingsGroup makePluginOptionsGroup() {
SettingsGroup pluginsGroup = new SettingsGroup(NLS.str("preferences.plugins"));
JadxPluginManager pluginManager = mainWindow.getWrapper().getDecompiler().getPluginManager();
for (JadxPlugin plugin : pluginManager.getAllPlugins()) {
for (JadxPlugin plugin : mainWindow.getWrapper().getAllPlugins()) {
if (!(plugin instanceof JadxPluginOptions)) {
continue;
}
......
......@@ -16,10 +16,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeInfo;
import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JavaNode;
import jadx.api.metadata.ICodeAnnotation;
import jadx.gui.JadxWrapper;
import jadx.gui.settings.JadxProject;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
......@@ -222,7 +222,7 @@ public final class CodeArea extends AbstractCodeArea {
return null;
}
try {
return getDecompiler().getJavaNodeAtPosition(getCodeInfo(), offset);
return getJadxWrapper().getDecompiler().getJavaNodeAtPosition(getCodeInfo(), offset);
} catch (Exception e) {
LOG.error("Can't get java node by offset: {}", offset, e);
}
......@@ -231,7 +231,7 @@ public final class CodeArea extends AbstractCodeArea {
public JavaNode getClosestJavaNode(int offset) {
try {
return getDecompiler().getClosestJavaNode(getCodeInfo(), offset);
return getJadxWrapper().getDecompiler().getClosestJavaNode(getCodeInfo(), offset);
} catch (Exception e) {
LOG.error("Can't get java node by offset: {}", offset, e);
return null;
......@@ -244,7 +244,7 @@ public final class CodeArea extends AbstractCodeArea {
if (codeInfo.hasMetadata()) {
ICodeAnnotation ann = codeInfo.getCodeMetadata().getAt(pos);
if (ann != null && ann.getAnnType() == ICodeAnnotation.AnnType.CLASS) {
return (JavaClass) getDecompiler().getJavaNodeByCodeAnnotation(codeInfo, ann);
return (JavaClass) getJadxWrapper().getDecompiler().getJavaNodeByCodeAnnotation(codeInfo, ann);
}
}
} catch (Exception e) {
......@@ -275,8 +275,8 @@ public final class CodeArea extends AbstractCodeArea {
return contentPanel.getTabbedPane().getMainWindow();
}
public JadxDecompiler getDecompiler() {
return getMainWindow().getWrapper().getDecompiler();
public JadxWrapper getJadxWrapper() {
return getMainWindow().getWrapper();
}
public JadxProject getProject() {
......
......@@ -11,7 +11,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeInfo;
import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JavaMethod;
import jadx.api.JavaNode;
......@@ -25,6 +24,7 @@ import jadx.api.metadata.ICodeMetadata;
import jadx.api.metadata.ICodeNodeRef;
import jadx.api.metadata.annotations.InsnCodeOffset;
import jadx.api.metadata.annotations.NodeDeclareRef;
import jadx.gui.JadxWrapper;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.dialog.CommentDialog;
......@@ -87,7 +87,7 @@ public class CommentAction extends AbstractAction implements DefaultPopupMenuLis
return null;
}
try {
JadxDecompiler decompiler = codeArea.getDecompiler();
JadxWrapper wrapper = codeArea.getJadxWrapper();
ICodeInfo codeInfo = codeArea.getCodeInfo();
ICodeMetadata metadata = codeInfo.getCodeMetadata();
int lineStartPos = codeArea.getLineStartFor(pos);
......@@ -95,7 +95,7 @@ public class CommentAction extends AbstractAction implements DefaultPopupMenuLis
// add method line comment by instruction offset
ICodeAnnotation offsetAnn = metadata.searchUp(pos, lineStartPos, AnnType.OFFSET);
if (offsetAnn instanceof InsnCodeOffset) {
JavaNode node = decompiler.getJavaNodeByRef(metadata.getNodeAt(pos));
JavaNode node = wrapper.getJavaNodeByRef(metadata.getNodeAt(pos));
if (node instanceof JavaMethod) {
int rawOffset = ((InsnCodeOffset) offsetAnn).getOffset();
JadxNodeRef nodeRef = JadxNodeRef.forMth((JavaMethod) node);
......@@ -114,7 +114,7 @@ public class CommentAction extends AbstractAction implements DefaultPopupMenuLis
return null;
});
if (nodeDef != null) {
JadxNodeRef nodeRef = JadxNodeRef.forJavaNode(decompiler.getJavaNodeByRef(nodeDef));
JadxNodeRef nodeRef = JadxNodeRef.forJavaNode(wrapper.getJavaNodeByRef(nodeDef));
return new JadxCodeComment(nodeRef, "");
}
......@@ -128,7 +128,7 @@ public class CommentAction extends AbstractAction implements DefaultPopupMenuLis
return null;
});
if (nodeRef != null) {
JavaNode defNode = decompiler.getJavaNodeByRef(nodeRef);
JavaNode defNode = wrapper.getJavaNodeByRef(nodeRef);
return new JadxCodeComment(JadxNodeRef.forJavaNode(defNode), "");
}
}
......
......@@ -65,7 +65,7 @@ public class CommentDialog extends JDialog {
Collections.sort(list);
codeData.setComments(list);
project.setCodeData(codeData);
codeArea.getMainWindow().getWrapper().getDecompiler().reloadCodeData();
codeArea.getMainWindow().getWrapper().reloadCodeData();
} catch (Exception e) {
LOG.error("Comment action failed", e);
}
......
......@@ -121,7 +121,7 @@ public class ExcludePkgDialog extends JDialog {
}
private void initPackageList() {
List<String> pkgs = mainWindow.getWrapper().getDecompiler().getPackages()
List<String> pkgs = mainWindow.getWrapper().getPackages()
.stream()
.map(JavaPackage::getFullName)
.collect(Collectors.toList());
......
......@@ -38,8 +38,6 @@ import jadx.api.data.impl.JadxCodeData;
import jadx.api.data.impl.JadxCodeRef;
import jadx.api.data.impl.JadxCodeRename;
import jadx.api.data.impl.JadxNodeRef;
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.rename.RenameVisitor;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.jobs.TaskStatus;
......@@ -168,12 +166,11 @@ public class RenameDialog extends JDialog {
Collections.sort(list);
codeData.setRenames(list);
project.setCodeData(codeData);
mainWindow.getWrapper().getDecompiler().reloadCodeData();
mainWindow.getWrapper().reloadCodeData();
}
private void refreshState() {
RootNode rootNode = mainWindow.getWrapper().getDecompiler().getRoot();
new RenameVisitor().init(rootNode);
mainWindow.getWrapper().reInitRenameVisitor();
JNodeCache nodeCache = cache.getNodeCache();
JavaNode javaNode = node.getJavaNode();
......
......@@ -16,11 +16,11 @@ import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import jadx.api.ICodeInfo;
import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JavaMethod;
import jadx.api.JavaNode;
import jadx.api.utils.CodeUtils;
import jadx.gui.JadxWrapper;
import jadx.gui.jobs.TaskStatus;
import jadx.gui.treemodel.CodeNode;
import jadx.gui.treemodel.JMethod;
......@@ -97,14 +97,14 @@ public class UsageDialog extends CommonSearchDialog {
private void processUsage(JavaNode searchNode, JavaClass topUseClass) {
ICodeInfo codeInfo = topUseClass.getCodeInfo();
String code = codeInfo.getCodeStr();
JadxDecompiler decompiler = mainWindow.getWrapper().getDecompiler();
JadxWrapper wrapper = mainWindow.getWrapper();
List<Integer> usePositions = topUseClass.getUsePlacesFor(codeInfo, searchNode);
for (int pos : usePositions) {
String line = CodeUtils.getLineForPos(code, pos);
if (line.startsWith("import ")) {
continue;
}
JavaNode enclosingNode = decompiler.getEnclosingNode(codeInfo, pos);
JavaNode enclosingNode = wrapper.getEnclosingNode(codeInfo, pos);
JavaNode usageNode = enclosingNode == null ? topUseClass : enclosingNode;
usageList.add(new CodeNode(getNodeCache().makeFrom(usageNode), line.trim(), pos));
}
......
......@@ -13,7 +13,6 @@ import javax.swing.ImageIcon;
import org.apache.commons.text.StringEscapeUtils;
import jadx.api.ICodeInfo;
import jadx.api.JadxDecompiler;
import jadx.api.impl.SimpleCodeInfo;
import jadx.core.dex.attributes.IAttributeNode;
import jadx.core.dex.nodes.ClassNode;
......@@ -21,6 +20,7 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.ProcessState;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.Utils;
import jadx.gui.JadxWrapper;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.MainWindow;
......@@ -35,9 +35,11 @@ public class SummaryNode extends JNode {
private static final ImageIcon ICON = UiUtils.openSvgIcon("nodes/detailView");
private final MainWindow mainWindow;
private final JadxWrapper wrapper;
public SummaryNode(MainWindow mainWindow) {
this.mainWindow = mainWindow;
this.wrapper = mainWindow.getWrapper();
}
@Override
......@@ -60,17 +62,16 @@ public class SummaryNode extends JNode {
private void writeInputSummary(StringEscapeUtils.Builder builder) throws IOException {
builder.append("<h2>Input</h2>");
JadxDecompiler jadx = mainWindow.getWrapper().getDecompiler();
builder.append("<h3>Files</h3>");
builder.append("<ul>");
for (File inputFile : jadx.getArgs().getInputFiles()) {
for (File inputFile : wrapper.getArgs().getInputFiles()) {
builder.append("<li>");
builder.escape(inputFile.getCanonicalFile().getAbsolutePath());
builder.append("</li>");
}
builder.append("</ul>");
List<ClassNode> classes = jadx.getRoot().getClasses(true);
List<ClassNode> classes = wrapper.getRootNode().getClasses(true);
List<String> codeSources = classes.stream()
.map(ClassNode::getInputFileName)
.distinct()
......@@ -108,8 +109,7 @@ public class SummaryNode extends JNode {
private void writeDecompilationSummary(StringEscapeUtils.Builder builder) {
builder.append("<h2>Decompilation</h2>");
JadxDecompiler jadx = mainWindow.getWrapper().getDecompiler();
List<ClassNode> classes = jadx.getRoot().getClasses(false);
List<ClassNode> classes = wrapper.getRootNode().getClasses(false);
int classesCount = classes.size();
long processedClasses = classes.stream().filter(c -> c.getState() == ProcessState.PROCESS_COMPLETE).count();
long generatedClasses = classes.stream().filter(c -> c.getState() == ProcessState.GENERATED_AND_UNLOADED).count();
......@@ -119,7 +119,7 @@ public class SummaryNode extends JNode {
builder.append("<li>Code generated: " + valueAndPercent(generatedClasses, classesCount) + "</li>");
builder.append("</ul>");
ErrorsCounter counter = jadx.getRoot().getErrorsCounter();
ErrorsCounter counter = wrapper.getRootNode().getErrorsCounter();
Set<IAttributeNode> problemNodes = new HashSet<>();
problemNodes.addAll(counter.getErrorNodes());
problemNodes.addAll(counter.getWarnNodes());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册