Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
极致猎手
jadx
提交
dd1be303
J
jadx
项目概览
极致猎手
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
dd1be303
编写于
2月 05, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(gui): split decompile and index tasks for correct time counting (#1361)
上级
8b30b770
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
326 addition
and
82 deletion
+326
-82
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+7
-1
jadx-core/src/main/java/jadx/api/JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+4
-0
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+11
-0
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
+48
-10
jadx-gui/src/main/java/jadx/gui/jobs/DecompileTask.java
jadx-gui/src/main/java/jadx/gui/jobs/DecompileTask.java
+26
-55
jadx-gui/src/main/java/jadx/gui/jobs/ExportTask.java
jadx-gui/src/main/java/jadx/gui/jobs/ExportTask.java
+4
-4
jadx-gui/src/main/java/jadx/gui/jobs/IBackgroundTask.java
jadx-gui/src/main/java/jadx/gui/jobs/IBackgroundTask.java
+11
-1
jadx-gui/src/main/java/jadx/gui/jobs/ITaskInfo.java
jadx-gui/src/main/java/jadx/gui/jobs/ITaskInfo.java
+13
-0
jadx-gui/src/main/java/jadx/gui/jobs/IndexService.java
jadx-gui/src/main/java/jadx/gui/jobs/IndexService.java
+21
-5
jadx-gui/src/main/java/jadx/gui/jobs/IndexTask.java
jadx-gui/src/main/java/jadx/gui/jobs/IndexTask.java
+94
-0
jadx-gui/src/main/java/jadx/gui/jobs/ProcessResult.java
jadx-gui/src/main/java/jadx/gui/jobs/ProcessResult.java
+25
-0
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+53
-3
jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
+2
-1
jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
+2
-1
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
+2
-1
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
+1
-0
未找到文件。
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
浏览文件 @
dd1be303
...
...
@@ -310,7 +310,13 @@ public final class JadxDecompiler implements Closeable {
}
processQueue
.
add
(
cls
);
}
for
(
List
<
JavaClass
>
decompileBatch
:
decompileScheduler
.
buildBatches
(
processQueue
))
{
List
<
List
<
JavaClass
>>
batches
;
try
{
batches
=
decompileScheduler
.
buildBatches
(
processQueue
);
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Decompilation batches build failed"
,
e
);
}
for
(
List
<
JavaClass
>
decompileBatch
:
batches
)
{
tasks
.
add
(()
->
{
for
(
JavaClass
cls
:
decompileBatch
)
{
try
{
...
...
jadx-core/src/main/java/jadx/api/JavaClass.java
浏览文件 @
dd1be303
...
...
@@ -69,6 +69,10 @@ public final class JavaClass implements JavaNode {
cls
.
unloadCode
();
}
public
boolean
isNoCode
()
{
return
cls
.
contains
(
AFlag
.
DONT_GENERATE
);
}
public
synchronized
String
getSmali
()
{
return
cls
.
getDisassembledCode
();
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
浏览文件 @
dd1be303
...
...
@@ -358,6 +358,17 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
return
codeInfo
;
}
@Nullable
public
ICodeInfo
getCodeFromCache
()
{
ICodeCache
codeCache
=
root
().
getCodeCache
();
String
clsRawName
=
getRawName
();
ICodeInfo
codeInfo
=
codeCache
.
get
(
clsRawName
);
if
(
codeInfo
==
ICodeInfo
.
EMPTY
)
{
return
null
;
}
return
codeInfo
;
}
@Override
public
void
load
()
{
for
(
MethodNode
mth
:
getMethods
())
{
...
...
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
浏览文件 @
dd1be303
...
...
@@ -15,8 +15,10 @@ import org.jetbrains.annotations.Nullable;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.panel.ProgressPanel
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.UiUtils
;
/**
...
...
@@ -46,6 +48,14 @@ public class BackgroundExecutor {
return
taskWorker
;
}
public
TaskStatus
executeAndWait
(
IBackgroundTask
task
)
{
try
{
return
execute
(
task
).
get
();
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Task execution error"
,
e
);
}
}
public
void
cancelAll
()
{
try
{
taskQueueExecutor
.
shutdownNow
();
...
...
@@ -74,11 +84,12 @@ public class BackgroundExecutor {
return
(
ThreadPoolExecutor
)
Executors
.
newFixedThreadPool
(
1
);
}
private
final
class
TaskWorker
extends
SwingWorker
<
TaskStatus
,
Void
>
{
private
final
class
TaskWorker
extends
SwingWorker
<
TaskStatus
,
Void
>
implements
ITaskInfo
{
private
final
IBackgroundTask
task
;
private
TaskStatus
status
=
TaskStatus
.
WAIT
;
private
long
jobsCount
;
private
long
jobsComplete
;
private
long
time
;
public
TaskWorker
(
IBackgroundTask
task
)
{
this
.
task
=
task
;
...
...
@@ -111,13 +122,15 @@ public class BackgroundExecutor {
executor
.
execute
(
job
);
}
executor
.
shutdown
();
status
=
waitTermination
(
executor
);
long
startTime
=
System
.
currentTimeMillis
();
status
=
waitTermination
(
executor
,
buildCancelCheck
(
startTime
));
time
=
System
.
currentTimeMillis
()
-
startTime
;
jobsComplete
=
executor
.
getCompletedTaskCount
();
task
.
onDone
(
this
);
}
@SuppressWarnings
(
"BusyWait"
)
private
TaskStatus
waitTermination
(
ThreadPoolExecutor
executor
)
throws
InterruptedException
{
Supplier
<
TaskStatus
>
cancelCheck
=
buildCancelCheck
();
private
TaskStatus
waitTermination
(
ThreadPoolExecutor
executor
,
Supplier
<
TaskStatus
>
cancelCheck
)
throws
InterruptedException
{
try
{
int
k
=
0
;
while
(
true
)
{
...
...
@@ -145,7 +158,7 @@ public class BackgroundExecutor {
}
private
void
performCancel
(
ThreadPoolExecutor
executor
)
throws
InterruptedException
{
progressPane
.
changeLabel
(
this
,
task
.
getTitle
()
+
" (
Canceling
)… "
);
progressPane
.
changeLabel
(
this
,
task
.
getTitle
()
+
" (
"
+
NLS
.
str
(
"progress.canceling"
)
+
"
)… "
);
progressPane
.
changeIndeterminate
(
this
,
true
);
// force termination
executor
.
shutdownNow
();
...
...
@@ -153,8 +166,8 @@ public class BackgroundExecutor {
LOG
.
debug
(
"Task cancel complete: {}"
,
complete
);
}
private
Supplier
<
TaskStatus
>
buildCancelCheck
()
{
long
waitUntilTime
=
task
.
timeLimit
()
==
0
?
0
:
System
.
currentTimeMillis
()
+
task
.
timeLimit
();
private
Supplier
<
TaskStatus
>
buildCancelCheck
(
long
startTime
)
{
long
waitUntilTime
=
task
.
timeLimit
()
==
0
?
0
:
startTime
+
task
.
timeLimit
();
boolean
checkMemoryUsage
=
task
.
checkMemoryUsage
();
return
()
->
{
if
(
waitUntilTime
!=
0
&&
waitUntilTime
<
System
.
currentTimeMillis
())
{
...
...
@@ -180,7 +193,32 @@ public class BackgroundExecutor {
@Override
protected
void
done
()
{
progressPane
.
setVisible
(
false
);
task
.
onFinish
(
status
,
jobsCount
-
jobsComplete
);
task
.
onFinish
(
this
);
}
@Override
public
TaskStatus
getStatus
()
{
return
status
;
}
@Override
public
long
getJobsCount
()
{
return
jobsCount
;
}
@Override
public
long
getJobsComplete
()
{
return
jobsComplete
;
}
@Override
public
long
getJobsSkipped
()
{
return
jobsCount
-
jobsComplete
;
}
@Override
public
long
getTime
()
{
return
time
;
}
}
...
...
@@ -206,9 +244,9 @@ public class BackgroundExecutor {
}
@Override
public
void
onFinish
(
TaskStatus
status
,
long
l
)
{
public
void
onFinish
(
ITaskInfo
taskInfo
)
{
if
(
onFinish
!=
null
)
{
onFinish
.
accept
(
status
);
onFinish
.
accept
(
taskInfo
.
getStatus
()
);
}
}
...
...
jadx-gui/src/main/java/jadx/gui/jobs/DecompileTask.java
浏览文件 @
dd1be303
package
jadx.gui.jobs
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.stream.Collectors
;
import
javax.swing.JOptionPane
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -29,7 +27,8 @@ public class DecompileTask implements IBackgroundTask {
private
final
JadxWrapper
wrapper
;
private
final
AtomicInteger
complete
=
new
AtomicInteger
(
0
);
private
int
expectedCompleteCount
;
private
long
startTime
;
private
ProcessResult
result
;
public
DecompileTask
(
MainWindow
mainWindow
,
JadxWrapper
wrapper
)
{
this
.
mainWindow
=
mainWindow
;
...
...
@@ -44,18 +43,21 @@ public class DecompileTask implements IBackgroundTask {
@Override
public
List
<
Runnable
>
scheduleJobs
()
{
IndexService
indexService
=
mainWindow
.
getCacheObject
().
getIndexService
();
List
<
JavaClass
>
classesForIndex
=
wrapper
.
getIncludedClasses
()
.
stream
()
.
filter
(
indexService:
:
isIndexNeeded
)
.
collect
(
Collectors
.
toList
());
expectedCompleteCount
=
classesForIndex
.
size
();
List
<
JavaClass
>
classes
=
wrapper
.
getIncludedClasses
();
expectedCompleteCount
=
classes
.
size
();
indexService
.
setComplete
(
false
);
complete
.
set
(
0
);
List
<
Runnable
>
jobs
=
new
ArrayList
<>(
expectedCompleteCount
+
1
);
jobs
.
add
(
indexService:
:
indexResources
);
for
(
List
<
JavaClass
>
batch
:
wrapper
.
buildDecompileBatches
(
classesForIndex
))
{
List
<
List
<
JavaClass
>>
batches
;
try
{
batches
=
wrapper
.
buildDecompileBatches
(
classes
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Decompile batches build error"
,
e
);
return
Collections
.
emptyList
();
}
List
<
Runnable
>
jobs
=
new
ArrayList
<>(
batches
.
size
());
for
(
List
<
JavaClass
>
batch
:
batches
)
{
jobs
.
add
(()
->
{
for
(
JavaClass
cls
:
batch
)
{
try
{
...
...
@@ -68,58 +70,23 @@ public class DecompileTask implements IBackgroundTask {
}
});
}
jobs
.
add
(()
->
{
for
(
JavaClass
cls
:
classesForIndex
)
{
try
{
// TODO: a lot of synchronizations to index object, not effective for parallel usage
indexService
.
indexCls
(
cls
);
}
catch
(
Throwable
e
)
{
LOG
.
error
(
"Failed to index class: {}"
,
cls
,
e
);
}
}
});
startTime
=
System
.
currentTimeMillis
();
return
jobs
;
}
@Override
public
void
on
Finish
(
TaskStatus
status
,
long
skippedJobs
)
{
long
taskTime
=
System
.
currentTimeMillis
()
-
startTime
;
public
void
on
Done
(
ITaskInfo
taskInfo
)
{
long
taskTime
=
taskInfo
.
getTime
()
;
long
avgPerCls
=
taskTime
/
Math
.
max
(
expectedCompleteCount
,
1
);
int
timeLimit
=
timeLimit
();
int
skippedCls
=
expectedCompleteCount
-
complete
.
get
();
if
(
LOG
.
isInfoEnabled
())
{
LOG
.
info
(
"Decompile task complete in "
+
taskTime
+
" ms (avg "
+
avgPerCls
+
" ms per class)"
+
", classes: "
+
expectedCompleteCount
+
", time limit:{ total: "
+
timeLimit
()
+
"ms, per cls: "
+
CLS_LIMIT
+
"ms }"
+
", status: "
+
status
);
}
IndexService
indexService
=
mainWindow
.
getCacheObject
().
getIndexService
();
indexService
.
setComplete
(
true
);
if
(
skippedJobs
==
0
)
{
return
;
}
int
skippedCls
=
expectedCompleteCount
-
complete
.
get
();
LOG
.
warn
(
"Decompile and indexing of some classes skipped: {}, status: {}"
,
skippedCls
,
status
);
switch
(
status
)
{
case
CANCEL_BY_USER:
{
String
reason
=
NLS
.
str
(
"message.userCancelTask"
);
String
message
=
NLS
.
str
(
"message.indexIncomplete"
,
reason
,
skippedCls
);
JOptionPane
.
showMessageDialog
(
mainWindow
,
message
);
break
;
}
case
CANCEL_BY_TIMEOUT:
{
String
reason
=
NLS
.
str
(
"message.taskTimeout"
,
timeLimit
());
String
message
=
NLS
.
str
(
"message.indexIncomplete"
,
reason
,
skippedCls
);
JOptionPane
.
showMessageDialog
(
mainWindow
,
message
);
break
;
}
case
CANCEL_BY_MEMORY:
{
mainWindow
.
showHeapUsageBar
();
JOptionPane
.
showMessageDialog
(
mainWindow
,
NLS
.
str
(
"message.indexingClassesSkipped"
,
skippedCls
));
break
;
}
+
", skipped: "
+
skippedCls
+
", time limit:{ total: "
+
timeLimit
+
"ms, per cls: "
+
CLS_LIMIT
+
"ms }"
+
", status: "
+
taskInfo
.
getStatus
());
}
this
.
result
=
new
ProcessResult
(
skippedCls
,
taskInfo
.
getStatus
(),
timeLimit
);
}
@Override
...
...
@@ -136,4 +103,8 @@ public class DecompileTask implements IBackgroundTask {
public
boolean
checkMemoryUsage
()
{
return
true
;
}
public
ProcessResult
getResult
()
{
return
result
;
}
}
jadx-gui/src/main/java/jadx/gui/jobs/ExportTask.java
浏览文件 @
dd1be303
...
...
@@ -50,16 +50,16 @@ public class ExportTask implements IBackgroundTask {
}
@Override
public
void
onFinish
(
TaskStatus
status
,
long
skipped
)
{
public
void
onFinish
(
ITaskInfo
taskInfo
)
{
// restore initial code cache
wrapper
.
getArgs
().
setCodeCache
(
uiCodeCache
);
if
(
skipped
==
0
)
{
if
(
taskInfo
.
getJobsSkipped
()
==
0
)
{
return
;
}
String
reason
=
getIncompleteReason
(
status
);
String
reason
=
getIncompleteReason
(
taskInfo
.
getStatus
()
);
if
(
reason
!=
null
)
{
JOptionPane
.
showMessageDialog
(
mainWindow
,
NLS
.
str
(
"message.saveIncomplete"
,
reason
,
skipped
),
NLS
.
str
(
"message.saveIncomplete"
,
reason
,
taskInfo
.
getJobsSkipped
()
),
NLS
.
str
(
"message.errorTitle"
),
JOptionPane
.
ERROR_MESSAGE
);
}
}
...
...
jadx-gui/src/main/java/jadx/gui/jobs/IBackgroundTask.java
浏览文件 @
dd1be303
...
...
@@ -8,7 +8,17 @@ public interface IBackgroundTask {
List
<
Runnable
>
scheduleJobs
();
void
onFinish
(
TaskStatus
status
,
long
skipped
);
/**
* Called on executor thread after the all jobs finished.
*/
default
void
onDone
(
ITaskInfo
taskInfo
)
{
}
/**
* Executed on the Event Dispatch Thread after the all jobs finished.
*/
default
void
onFinish
(
ITaskInfo
taskInfo
)
{
}
default
boolean
canBeCanceled
()
{
return
false
;
...
...
jadx-gui/src/main/java/jadx/gui/jobs/ITaskInfo.java
0 → 100644
浏览文件 @
dd1be303
package
jadx.gui.jobs
;
public
interface
ITaskInfo
{
TaskStatus
getStatus
();
long
getJobsCount
();
long
getJobsComplete
();
long
getJobsSkipped
();
long
getTime
();
}
jadx-gui/src/main/java/jadx/gui/jobs/IndexService.java
浏览文件 @
dd1be303
...
...
@@ -5,9 +5,11 @@ import java.util.List;
import
java.util.Set
;
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.ICodeWriter
;
import
jadx.api.JavaClass
;
import
jadx.gui.utils.CacheObject
;
...
...
@@ -30,22 +32,36 @@ public class IndexService {
/**
* Warning! Not ready for parallel execution. Use only in a single thread.
*/
public
void
indexCls
(
JavaClass
cls
)
{
public
boolean
indexCls
(
JavaClass
cls
)
{
try
{
TextSearchIndex
index
=
cache
.
getTextIndex
();
if
(
index
==
null
)
{
return
;
return
false
;
}
List
<
StringRef
>
lines
=
splitLines
(
cls
);
// get code from cache to avoid decompilation here
String
code
=
getCodeFromCache
(
cls
);
if
(
code
==
null
)
{
return
cls
.
isNoCode
();
}
List
<
StringRef
>
lines
=
splitLines
(
code
);
CodeLinesInfo
linesInfo
=
new
CodeLinesInfo
(
cls
);
index
.
indexCode
(
cls
,
linesInfo
,
lines
);
index
.
indexNames
(
cls
);
indexSet
.
add
(
cls
);
return
true
;
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Index error in class: {}"
,
cls
.
getFullName
(),
e
);
return
false
;
}
}
// TODO: add to API
@Nullable
private
String
getCodeFromCache
(
JavaClass
cls
)
{
ICodeInfo
codeInfo
=
cls
.
getClassNode
().
getCodeFromCache
();
return
codeInfo
!=
null
?
codeInfo
.
getCodeStr
()
:
null
;
}
public
void
indexResources
()
{
TextSearchIndex
index
=
cache
.
getTextIndex
();
index
.
indexResource
();
...
...
@@ -75,8 +91,8 @@ public class IndexService {
}
@NotNull
protected
static
List
<
StringRef
>
splitLines
(
JavaClass
cls
)
{
List
<
StringRef
>
lines
=
StringRef
.
split
(
c
ls
.
getCode
()
,
ICodeWriter
.
NL
);
protected
static
List
<
StringRef
>
splitLines
(
String
code
)
{
List
<
StringRef
>
lines
=
StringRef
.
split
(
c
ode
,
ICodeWriter
.
NL
);
int
size
=
lines
.
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
lines
.
set
(
i
,
lines
.
get
(
i
).
trim
());
...
...
jadx-gui/src/main/java/jadx/gui/jobs/IndexTask.java
0 → 100644
浏览文件 @
dd1be303
package
jadx.gui.jobs
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.stream.Collectors
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.JavaClass
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.NLS
;
public
class
IndexTask
implements
IBackgroundTask
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
IndexTask
.
class
);
private
final
MainWindow
mainWindow
;
private
final
JadxWrapper
wrapper
;
private
final
AtomicInteger
complete
=
new
AtomicInteger
(
0
);
private
int
expectedCompleteCount
;
private
ProcessResult
result
;
public
IndexTask
(
MainWindow
mainWindow
,
JadxWrapper
wrapper
)
{
this
.
mainWindow
=
mainWindow
;
this
.
wrapper
=
wrapper
;
}
@Override
public
String
getTitle
()
{
return
NLS
.
str
(
"progress.index"
);
}
@Override
public
List
<
Runnable
>
scheduleJobs
()
{
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
<>(
2
);
jobs
.
add
(
indexService:
:
indexResources
);
jobs
.
add
(()
->
{
for
(
JavaClass
cls
:
classesForIndex
)
{
try
{
// TODO: a lot of synchronizations to index object, not efficient for parallel usage
if
(
indexService
.
indexCls
(
cls
))
{
complete
.
incrementAndGet
();
}
else
{
LOG
.
debug
(
"Index skipped for {}"
,
cls
);
}
}
catch
(
Throwable
e
)
{
LOG
.
error
(
"Failed to index class: {}"
,
cls
,
e
);
}
}
});
return
jobs
;
}
@Override
public
void
onDone
(
ITaskInfo
taskInfo
)
{
int
skippedCls
=
expectedCompleteCount
-
complete
.
get
();
if
(
LOG
.
isInfoEnabled
())
{
LOG
.
info
(
"Index task complete in "
+
taskInfo
.
getTime
()
+
" ms"
+
", classes: "
+
expectedCompleteCount
+
", skipped: "
+
skippedCls
+
", status: "
+
taskInfo
.
getStatus
());
}
IndexService
indexService
=
mainWindow
.
getCacheObject
().
getIndexService
();
indexService
.
setComplete
(
true
);
this
.
result
=
new
ProcessResult
(
skippedCls
,
taskInfo
.
getStatus
(),
0
);
}
@Override
public
boolean
canBeCanceled
()
{
return
true
;
}
@Override
public
boolean
checkMemoryUsage
()
{
return
true
;
}
public
ProcessResult
getResult
()
{
return
result
;
}
}
jadx-gui/src/main/java/jadx/gui/jobs/ProcessResult.java
0 → 100644
浏览文件 @
dd1be303
package
jadx.gui.jobs
;
public
class
ProcessResult
{
private
final
int
skipped
;
private
final
TaskStatus
status
;
private
final
int
timeLimit
;
public
ProcessResult
(
int
skipped
,
TaskStatus
status
,
int
timeLimit
)
{
this
.
skipped
=
skipped
;
this
.
status
=
status
;
this
.
timeLimit
=
timeLimit
;
}
public
int
getSkipped
()
{
return
skipped
;
}
public
TaskStatus
getStatus
()
{
return
status
;
}
public
int
getTimeLimit
()
{
return
timeLimit
;
}
}
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
浏览文件 @
dd1be303
...
...
@@ -30,6 +30,7 @@ import java.nio.file.Path;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.EnumSet
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Locale
;
...
...
@@ -38,7 +39,6 @@ import java.util.Timer;
import
java.util.TimerTask
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Future
;
import
java.util.stream.Collectors
;
import
javax.swing.AbstractAction
;
...
...
@@ -94,6 +94,8 @@ import jadx.gui.jobs.BackgroundExecutor;
import
jadx.gui.jobs.DecompileTask
;
import
jadx.gui.jobs.ExportTask
;
import
jadx.gui.jobs.IndexService
;
import
jadx.gui.jobs.IndexTask
;
import
jadx.gui.jobs.ProcessResult
;
import
jadx.gui.jobs.TaskStatus
;
import
jadx.gui.plugins.quark.QuarkDialog
;
import
jadx.gui.settings.JadxProject
;
...
...
@@ -555,14 +557,62 @@ public class MainWindow extends JFrame {
}
try
{
DecompileTask
decompileTask
=
new
DecompileTask
(
this
,
wrapper
);
Future
<
TaskStatus
>
task
=
backgroundExecutor
.
execute
(
decompileTask
);
task
.
get
();
backgroundExecutor
.
executeAndWait
(
decompileTask
);
IndexTask
indexTask
=
new
IndexTask
(
this
,
wrapper
);
backgroundExecutor
.
executeAndWait
(
indexTask
);
processDecompilationResults
(
decompileTask
.
getResult
(),
indexTask
.
getResult
());
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Decompile task execution failed"
,
e
);
}
}
}
private
void
processDecompilationResults
(
ProcessResult
decompile
,
ProcessResult
index
)
{
int
skippedCls
=
Math
.
max
(
decompile
.
getSkipped
(),
index
.
getSkipped
());
if
(
skippedCls
==
0
)
{
return
;
}
TaskStatus
status
=
mergeStatus
(
EnumSet
.
of
(
decompile
.
getStatus
(),
index
.
getStatus
()));
LOG
.
warn
(
"Decompile and indexing of some classes skipped: {}, status: {}"
,
skippedCls
,
status
);
switch
(
status
)
{
case
CANCEL_BY_USER:
{
String
reason
=
NLS
.
str
(
"message.userCancelTask"
);
String
message
=
NLS
.
str
(
"message.indexIncomplete"
,
reason
,
skippedCls
);
JOptionPane
.
showMessageDialog
(
this
,
message
);
break
;
}
case
CANCEL_BY_TIMEOUT:
{
String
reason
=
NLS
.
str
(
"message.taskTimeout"
,
decompile
.
getTimeLimit
());
String
message
=
NLS
.
str
(
"message.indexIncomplete"
,
reason
,
skippedCls
);
JOptionPane
.
showMessageDialog
(
this
,
message
);
break
;
}
case
CANCEL_BY_MEMORY:
{
showHeapUsageBar
();
JOptionPane
.
showMessageDialog
(
this
,
NLS
.
str
(
"message.indexingClassesSkipped"
,
skippedCls
));
break
;
}
}
}
private
TaskStatus
mergeStatus
(
Set
<
TaskStatus
>
statuses
)
{
if
(
statuses
.
size
()
==
1
)
{
return
statuses
.
iterator
().
next
();
}
if
(
statuses
.
contains
(
TaskStatus
.
CANCEL_BY_MEMORY
))
{
return
TaskStatus
.
CANCEL_BY_MEMORY
;
}
if
(
statuses
.
contains
(
TaskStatus
.
CANCEL_BY_TIMEOUT
))
{
return
TaskStatus
.
CANCEL_BY_TIMEOUT
;
}
if
(
statuses
.
contains
(
TaskStatus
.
CANCEL_BY_USER
))
{
return
TaskStatus
.
CANCEL_BY_USER
;
}
return
TaskStatus
.
COMPLETE
;
}
public
void
cancelBackgroundJobs
()
{
ExecutorService
worker
=
Executors
.
newSingleThreadExecutor
();
worker
.
execute
(
backgroundExecutor:
:
cancelAll
);
...
...
jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
浏览文件 @
dd1be303
...
...
@@ -38,6 +38,7 @@ tree.loading=Laden…
progress.load
=
Laden
progress.decompile
=
Dekompilieren
progress.index
=
Indizieren
#progress.canceling=Canceling
error_dialog.title
=
Fehler
...
...
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
浏览文件 @
dd1be303
...
...
@@ -37,7 +37,8 @@ tree.loading=Loading...
progress.load
=
Loading
progress.decompile
=
Decompiling
#progress.index=Indexing
progress.index
=
Indexing
progress.canceling
=
Canceling
error_dialog.title
=
Error
...
...
jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
浏览文件 @
dd1be303
...
...
@@ -38,6 +38,7 @@ tree.loading=Cargando...
progress.load
=
Cargando
progress.decompile
=
Decompiling
#progress.index=Indexing
#progress.canceling=Canceling
#error_dialog.title=
...
...
jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
浏览文件 @
dd1be303
...
...
@@ -38,6 +38,7 @@ tree.loading=로딩중...
progress.load
=
로딩중
progress.decompile
=
디컴파일 중
progress.index
=
인덱싱 중
#progress.canceling=Canceling
error_dialog.title
=
오류
...
...
@@ -193,7 +194,7 @@ popup.copy=붙여넣기
popup.paste
=
복사
popup.delete
=
삭제
popup.select_all
=
모두 선택
popup.frida
=
frida 스니펫으로 복사
popup.frida
=
frida 스니펫으로 복사
popup.find_usage
=
사용 찾기
popup.go_to_declaration
=
선언문으로 이동
popup.exclude
=
제외
...
...
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
浏览文件 @
dd1be303
...
...
@@ -37,7 +37,8 @@ tree.loading=加载中...
progress.load
=
正在加载
progress.decompile
=
反编译中
#progress.index=索引中
progress.index
=
索引中
#progress.canceling=Canceling
error_dialog.title
=
错误
...
...
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
浏览文件 @
dd1be303
...
...
@@ -38,6 +38,7 @@ tree.loading=載入中...
progress.load
=
載入中
progress.decompile
=
正在反編譯
#progress.index=Indexing
#progress.canceling=Canceling
error_dialog.title
=
錯誤
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录