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

feat(gui): don't run full decompilation for usage search

New approach will run partial decompilation for classes
from usage info collected on file load (pre-decompilation stage).
上级 3a298122
......@@ -201,9 +201,25 @@ public final class JavaClass implements JavaNode {
@Override
public JavaClass getTopParentClass() {
if (cls.contains(AFlag.ANONYMOUS_CLASS)) {
// moved to usage class
return getParentForAnonymousClass();
}
return parent == null ? this : parent.getTopParentClass();
}
private JavaClass getParentForAnonymousClass() {
List<JavaNode> useIn = getUseIn();
if (useIn.isEmpty()) {
return this;
}
JavaNode useNode = useIn.get(0);
if (useNode.equals(this)) {
return this;
}
return useNode.getTopParentClass();
}
public AccessInfo getAccessInfo() {
return cls.getAccessFlags();
}
......
......@@ -90,7 +90,7 @@ public class DbgUtils {
clsSig = DbgUtils.classSigToFullName(clsSig);
JavaClass cls = mainWindow.getWrapper().getDecompiler().searchJavaClassOrItsParentByOrigFullName(clsSig);
if (cls != null) {
JClass jc = (JClass) mainWindow.getCacheObject().getNodeCache().makeFrom(cls);
JClass jc = mainWindow.getCacheObject().getNodeCache().makeFrom(cls);
return jc.getRootClass();
}
return null;
......
......@@ -129,7 +129,7 @@ public class BackgroundExecutor {
return cancelStatus;
}
setProgress(calcProgress(executor.getCompletedTaskCount()));
Thread.sleep(500);
Thread.sleep(300);
}
} catch (InterruptedException e) {
LOG.debug("Task wait interrupted");
......
......@@ -3,6 +3,7 @@ package jadx.gui.jobs;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.swing.JOptionPane;
......@@ -42,15 +43,18 @@ public class DecompileTask implements IBackgroundTask {
@Override
public List<Runnable> scheduleJobs() {
List<JavaClass> classes = wrapper.getIncludedClasses();
expectedCompleteCount = classes.size();
IndexService indexService = mainWindow.getCacheObject().getIndexService();
List<JavaClass> classesForIndex = wrapper.getIncludedClasses()
.stream()
.filter(indexService::isIndexNeeded)
.collect(Collectors.toList());
expectedCompleteCount = classesForIndex.size();
indexService.setComplete(false);
complete.set(0);
List<Runnable> jobs = new ArrayList<>(expectedCompleteCount + 1);
for (JavaClass cls : classes) {
for (JavaClass cls : classesForIndex) {
jobs.add(() -> {
cls.decompile();
indexService.indexCls(cls);
......
package jadx.gui.jobs;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
......@@ -20,6 +22,7 @@ public class IndexService {
private final CacheObject cache;
private boolean indexComplete;
private final Set<JavaClass> indexSet = new HashSet<>();
public IndexService(CacheObject cache) {
this.cache = cache;
......@@ -40,6 +43,7 @@ public class IndexService {
usageInfo.processClass(cls, linesInfo, lines);
index.indexCode(cls, linesInfo, lines);
indexSet.add(cls);
} catch (Exception e) {
LOG.error("Index error in class: {}", cls.getFullName(), e);
}
......@@ -56,11 +60,16 @@ public class IndexService {
if (index == null || usageInfo == null) {
return;
}
indexSet.remove(cls);
index.remove(cls);
usageInfo.remove(cls);
indexCls(cls);
}
public boolean isIndexNeeded(JavaClass cls) {
return !indexSet.contains(cls);
}
@NotNull
protected static List<StringRef> splitLines(JavaClass cls) {
List<StringRef> lines = StringRef.split(cls.getCode(), ICodeWriter.NL);
......
......@@ -519,6 +519,9 @@ public class MainWindow extends JFrame {
public void waitDecompileTask() {
synchronized (DECOMPILER_TASK_SYNC) {
if (cacheObject.getIndexService().isComplete()) {
return;
}
try {
DecompileTask decompileTask = new DecompileTask(this, wrapper);
Future<TaskStatus> task = backgroundExecutor.execute(decompileTask);
......
......@@ -547,14 +547,14 @@ public abstract class CommonSearchDialog extends JDialog {
}
}
private void loadStartCommon() {
void loadStartCommon() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
progressPane.setIndeterminate(true);
progressPane.setVisible(true);
warnLabel.setVisible(false);
}
private void loadFinishedCommon() {
void loadFinishedCommon() {
setCursor(null);
progressPane.setVisible(false);
......
......@@ -3,6 +3,9 @@ package jadx.gui.ui.dialog;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
......@@ -10,10 +13,15 @@ import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import jadx.api.JavaClass;
import jadx.api.JavaNode;
import jadx.gui.jobs.IndexService;
import jadx.gui.jobs.TaskStatus;
import jadx.gui.treemodel.JNode;
import jadx.gui.ui.MainWindow;
import jadx.gui.utils.CodeUsageInfo;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
public class UsageDialog extends CommonSearchDialog {
......@@ -32,7 +40,40 @@ public class UsageDialog extends CommonSearchDialog {
@Override
protected void openInit() {
prepare();
IndexService indexService = mainWindow.getCacheObject().getIndexService();
if (indexService.isComplete()) {
loadFinishedCommon();
loadFinished();
return;
}
List<JavaNode> useIn = node.getJavaNode().getUseIn();
List<JavaClass> usageTopClsForIndex = useIn
.stream()
.map(JavaNode::getTopParentClass)
.filter(indexService::isIndexNeeded)
.distinct()
.sorted(Comparator.comparing(JavaClass::getFullName))
.collect(Collectors.toList());
if (usageTopClsForIndex.isEmpty()) {
loadFinishedCommon();
loadFinished();
return;
}
mainWindow.getBackgroundExecutor().execute(NLS.str("progress.load"),
() -> {
for (JavaClass cls : usageTopClsForIndex) {
cls.decompile();
indexService.indexCls(cls);
}
},
(status) -> {
if (status == TaskStatus.CANCEL_BY_MEMORY) {
mainWindow.showHeapUsageBar();
UiUtils.errorMessage(this, NLS.str("message.memoryLow"));
}
loadFinishedCommon();
loadFinished();
});
}
@Override
......
......@@ -31,25 +31,29 @@ public class JNodeCache {
return jNode;
}
public JClass makeFrom(JavaClass javaCls) {
if (javaCls == null) {
return null;
}
return (JClass) cache.computeIfAbsent(javaCls,
jn -> new JClass(javaCls, makeFrom(javaCls.getDeclaringClass())));
}
private JNode convert(JavaNode node) {
if (node == null) {
return null;
}
if (node instanceof JavaClass) {
JClass p = (JClass) makeFrom(node.getDeclaringClass());
return new JClass((JavaClass) node, p);
return new JClass((JavaClass) node, makeFrom(node.getDeclaringClass()));
}
if (node instanceof JavaMethod) {
JavaMethod mth = (JavaMethod) node;
return new JMethod(mth, (JClass) makeFrom(mth.getDeclaringClass()));
return new JMethod((JavaMethod) node, makeFrom(node.getDeclaringClass()));
}
if (node instanceof JavaField) {
JavaField fld = (JavaField) node;
return new JField(fld, (JClass) makeFrom(fld.getDeclaringClass()));
return new JField((JavaField) node, makeFrom(node.getDeclaringClass()));
}
if (node instanceof JavaVariable) {
JavaVariable var = (JavaVariable) node;
return new JVariable(var, (JClass) makeFrom(var.getDeclaringClass()));
return new JVariable((JavaVariable) node, makeFrom(node.getDeclaringClass()));
}
throw new JadxRuntimeException("Unknown type for JavaNode: " + node.getClass());
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册