Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
keyescgm
jadx
提交
ae265126
J
jadx
项目概览
keyescgm
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ae265126
编写于
8月 03, 2020
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: use internal usage info for rename, fix index refresh (#791)
上级
498c2f52
变更
30
隐藏空白更改
内联
并排
Showing
30 changed file
with
296 addition
and
363 deletion
+296
-363
jadx-core/src/main/java/jadx/api/ICodeCache.java
jadx-core/src/main/java/jadx/api/ICodeCache.java
+2
-0
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+10
-0
jadx-core/src/main/java/jadx/api/JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+8
-1
jadx-core/src/main/java/jadx/api/JavaField.java
jadx-core/src/main/java/jadx/api/JavaField.java
+7
-0
jadx-core/src/main/java/jadx/api/JavaMethod.java
jadx-core/src/main/java/jadx/api/JavaMethod.java
+5
-0
jadx-core/src/main/java/jadx/api/JavaNode.java
jadx-core/src/main/java/jadx/api/JavaNode.java
+4
-0
jadx-core/src/main/java/jadx/api/JavaPackage.java
jadx-core/src/main/java/jadx/api/JavaPackage.java
+6
-0
jadx-core/src/main/java/jadx/api/impl/InMemoryCodeCache.java
jadx-core/src/main/java/jadx/api/impl/InMemoryCodeCache.java
+5
-0
jadx-core/src/main/java/jadx/api/impl/NoOpCodeCache.java
jadx-core/src/main/java/jadx/api/impl/NoOpCodeCache.java
+5
-0
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+2
-2
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+3
-0
jadx-core/src/main/java/jadx/core/dex/nodes/ICodeNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ICodeNode.java
+1
-1
jadx-core/src/main/java/jadx/core/dex/nodes/IUsageInfoNode.java
...ore/src/main/java/jadx/core/dex/nodes/IUsageInfoNode.java
+7
-0
jadx-core/src/main/java/jadx/core/dex/visitors/usage/UsageInfoVisitor.java
...n/java/jadx/core/dex/visitors/usage/UsageInfoVisitor.java
+3
-4
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
+22
-7
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundWorker.java
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundWorker.java
+0
-17
jadx-gui/src/main/java/jadx/gui/jobs/IndexJob.java
jadx-gui/src/main/java/jadx/gui/jobs/IndexJob.java
+38
-18
jadx-gui/src/main/java/jadx/gui/jobs/RefreshJob.java
jadx-gui/src/main/java/jadx/gui/jobs/RefreshJob.java
+0
-28
jadx-gui/src/main/java/jadx/gui/jobs/UnloadJob.java
jadx-gui/src/main/java/jadx/gui/jobs/UnloadJob.java
+0
-31
jadx-gui/src/main/java/jadx/gui/treemodel/CodeNode.java
jadx-gui/src/main/java/jadx/gui/treemodel/CodeNode.java
+21
-0
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+5
-7
jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java
jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java
+80
-137
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
+0
-20
jadx-gui/src/main/java/jadx/gui/utils/CodeUsageInfo.java
jadx-gui/src/main/java/jadx/gui/utils/CodeUsageInfo.java
+10
-0
jadx-gui/src/main/java/jadx/gui/utils/JNodeCache.java
jadx-gui/src/main/java/jadx/gui/utils/JNodeCache.java
+0
-6
jadx-gui/src/main/java/jadx/gui/utils/search/CodeIndex.java
jadx-gui/src/main/java/jadx/gui/utils/search/CodeIndex.java
+12
-25
jadx-gui/src/main/java/jadx/gui/utils/search/SearchIndex.java
...-gui/src/main/java/jadx/gui/utils/search/SearchIndex.java
+0
-4
jadx-gui/src/main/java/jadx/gui/utils/search/SimpleIndex.java
...-gui/src/main/java/jadx/gui/utils/search/SimpleIndex.java
+19
-36
jadx-gui/src/main/java/jadx/gui/utils/search/TextSearchIndex.java
.../src/main/java/jadx/gui/utils/search/TextSearchIndex.java
+18
-16
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
+3
-3
未找到文件。
jadx-core/src/main/java/jadx/api/ICodeCache.java
浏览文件 @
ae265126
...
...
@@ -6,6 +6,8 @@ public interface ICodeCache {
void
add
(
String
clsFullName
,
ICodeInfo
codeInfo
);
void
remove
(
String
clsFullName
);
@Nullable
ICodeInfo
get
(
String
clsFullName
);
}
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
浏览文件 @
ae265126
...
...
@@ -4,16 +4,19 @@ import java.io.Closeable;
import
java.io.File
;
import
java.nio.file.Path
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.TimeUnit
;
import
java.util.function.Predicate
;
import
java.util.stream.Collectors
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
...
...
@@ -422,6 +425,13 @@ public final class JadxDecompiler implements Closeable {
throw
new
JadxRuntimeException
(
"Unexpected node type: "
+
obj
);
}
List
<
JavaNode
>
convertNodes
(
Collection
<?>
nodesList
)
{
return
nodesList
.
stream
()
.
map
(
this
::
convertNode
)
.
filter
(
Objects:
:
nonNull
)
.
collect
(
Collectors
.
toList
());
}
@Nullable
public
JavaNode
getJavaNodeAtPosition
(
ICodeInfo
codeInfo
,
int
line
,
int
offset
)
{
Map
<
CodePosition
,
Object
>
map
=
codeInfo
.
getAnnotations
();
...
...
jadx-core/src/main/java/jadx/api/JavaClass.java
浏览文件 @
ae265126
...
...
@@ -59,6 +59,8 @@ public final class JavaClass implements JavaNode {
public
synchronized
void
refresh
()
{
listsLoaded
=
false
;
cls
.
unload
();
cls
.
deepUnload
();
cls
.
reRunDecompile
();
}
...
...
@@ -124,7 +126,7 @@ public final class JavaClass implements JavaNode {
}
}
pr
ivate
JadxDecompiler
getRootDecompiler
()
{
pr
otected
JadxDecompiler
getRootDecompiler
()
{
if
(
parent
!=
null
)
{
return
parent
.
getRootDecompiler
();
}
...
...
@@ -156,6 +158,11 @@ public final class JavaClass implements JavaNode {
return
resultMap
;
}
@Override
public
List
<
JavaNode
>
getUseIn
()
{
return
getRootDecompiler
().
convertNodes
(
cls
.
getUseIn
());
}
@Nullable
@Deprecated
public
JavaNode
getJavaNodeAtPosition
(
int
line
,
int
offset
)
{
...
...
jadx-core/src/main/java/jadx/api/JavaField.java
浏览文件 @
ae265126
package
jadx.api
;
import
java.util.List
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.FieldNode
;
...
...
@@ -47,6 +49,11 @@ public final class JavaField implements JavaNode {
return
field
.
getDecompiledLine
();
}
@Override
public
List
<
JavaNode
>
getUseIn
()
{
return
getDeclaringClass
().
getRootDecompiler
().
convertNodes
(
field
.
getUseIn
());
}
/**
* Internal API. Not Stable!
*/
...
...
jadx-core/src/main/java/jadx/api/JavaMethod.java
浏览文件 @
ae265126
...
...
@@ -56,6 +56,11 @@ public final class JavaMethod implements JavaNode {
return
ArgType
.
tryToResolveClassAlias
(
mth
.
root
(),
retType
);
}
@Override
public
List
<
JavaNode
>
getUseIn
()
{
return
getDeclaringClass
().
getRootDecompiler
().
convertNodes
(
mth
.
getUseIn
());
}
public
boolean
isConstructor
()
{
return
mth
.
getMethodInfo
().
isConstructor
();
}
...
...
jadx-core/src/main/java/jadx/api/JavaNode.java
浏览文件 @
ae265126
package
jadx.api
;
import
java.util.List
;
public
interface
JavaNode
{
String
getName
();
...
...
@@ -11,4 +13,6 @@ public interface JavaNode {
JavaClass
getTopParentClass
();
int
getDecompiledLine
();
List
<
JavaNode
>
getUseIn
();
}
jadx-core/src/main/java/jadx/api/JavaPackage.java
浏览文件 @
ae265126
package
jadx.api
;
import
java.util.Collections
;
import
java.util.List
;
import
org.jetbrains.annotations.NotNull
;
...
...
@@ -43,6 +44,11 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
return
0
;
}
@Override
public
List
<
JavaNode
>
getUseIn
()
{
return
Collections
.
emptyList
();
}
@Override
public
int
compareTo
(
@NotNull
JavaPackage
o
)
{
return
name
.
compareTo
(
o
.
name
);
...
...
jadx-core/src/main/java/jadx/api/impl/InMemoryCodeCache.java
浏览文件 @
ae265126
...
...
@@ -17,6 +17,11 @@ public class InMemoryCodeCache implements ICodeCache {
storage
.
put
(
clsFullName
,
codeInfo
);
}
@Override
public
void
remove
(
String
clsFullName
)
{
storage
.
remove
(
clsFullName
);
}
@Override
public
@Nullable
ICodeInfo
get
(
String
clsFullName
)
{
return
storage
.
get
(
clsFullName
);
...
...
jadx-core/src/main/java/jadx/api/impl/NoOpCodeCache.java
浏览文件 @
ae265126
...
...
@@ -12,6 +12,11 @@ public class NoOpCodeCache implements ICodeCache {
// do nothing
}
@Override
public
void
remove
(
String
clsFullName
)
{
// do nothing
}
@Override
public
@Nullable
ICodeInfo
get
(
String
clsFullName
)
{
return
null
;
...
...
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
浏览文件 @
ae265126
...
...
@@ -699,12 +699,12 @@ public class ClassGen {
List
<
ClassNode
>
deps
=
cls
.
getDependencies
();
code
.
startLine
(
"// deps - "
).
add
(
Integer
.
toString
(
deps
.
size
()));
for
(
ClassNode
depCls
:
deps
)
{
code
.
startLine
(
"// "
).
add
(
depCls
.
getFullName
());
code
.
startLine
(
"// "
).
add
(
depCls
.
get
ClassInfo
().
get
FullName
());
}
List
<
ClassNode
>
useIn
=
cls
.
getUseIn
();
code
.
startLine
(
"// use in - "
).
add
(
Integer
.
toString
(
useIn
.
size
()));
for
(
ClassNode
useCls
:
useIn
)
{
code
.
startLine
(
"// "
).
add
(
useCls
.
getFullName
());
code
.
startLine
(
"// "
).
add
(
useCls
.
get
ClassInfo
().
get
FullName
());
}
List
<
MethodNode
>
useInMths
=
cls
.
getUseInMth
();
code
.
startLine
(
"// use in methods - "
).
add
(
Integer
.
toString
(
useInMths
.
size
()));
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
浏览文件 @
ae265126
...
...
@@ -345,6 +345,9 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
@Override
public
void
unload
()
{
if
(
state
==
NOT_LOADED
)
{
return
;
}
methods
.
forEach
(
MethodNode:
:
unload
);
innerClasses
.
forEach
(
ClassNode:
:
unload
);
fields
.
forEach
(
FieldNode:
:
unloadAttributes
);
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ICodeNode.java
浏览文件 @
ae265126
...
...
@@ -3,7 +3,7 @@ package jadx.core.dex.nodes;
import
jadx.core.dex.attributes.IAttributeNode
;
import
jadx.core.dex.info.AccessInfo
;
public
interface
ICodeNode
extends
IDexNode
,
IAttributeNode
{
public
interface
ICodeNode
extends
IDexNode
,
IAttributeNode
,
IUsageInfoNode
{
AccessInfo
getAccessFlags
();
void
setAccessFlags
(
AccessInfo
newAccessFlags
);
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/IUsageInfoNode.java
0 → 100644
浏览文件 @
ae265126
package
jadx.core.dex.nodes
;
import
java.util.List
;
public
interface
IUsageInfoNode
{
List
<?
extends
ICodeNode
>
getUseIn
();
}
jadx-core/src/main/java/jadx/core/dex/visitors/usage/UsageInfoVisitor.java
浏览文件 @
ae265126
...
...
@@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory;
import
jadx.api.plugins.input.data.ICodeReader
;
import
jadx.api.plugins.input.insns.InsnData
;
import
jadx.api.plugins.input.insns.Opcode
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
...
...
@@ -49,9 +48,6 @@ public class UsageInfoVisitor extends AbstractVisitor {
}
// TODO: process annotations and generics
for
(
MethodNode
methodNode
:
cls
.
getMethods
())
{
if
(
methodNode
.
isNoCode
()
||
methodNode
.
contains
(
AType
.
JADX_ERROR
))
{
continue
;
}
processMethod
(
methodNode
,
usageInfo
);
}
}
...
...
@@ -70,6 +66,9 @@ public class UsageInfoVisitor extends AbstractVisitor {
}
private
static
void
processInstructions
(
MethodNode
mth
,
UsageInfo
usageInfo
)
{
if
(
mth
.
isNoCode
())
{
return
;
}
ICodeReader
codeReader
=
mth
.
getCodeReader
();
if
(
codeReader
==
null
)
{
return
;
...
...
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
浏览文件 @
ae265126
...
...
@@ -7,7 +7,7 @@ import java.util.concurrent.Future;
import
java.util.concurrent.ThreadPoolExecutor
;
import
java.util.concurrent.TimeUnit
;
import
javax.swing.
SwingWorker
;
import
javax.swing.
*
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
...
...
@@ -36,8 +36,10 @@ public class BackgroundExecutor {
public
Future
<
Boolean
>
execute
(
IBackgroundTask
task
)
{
TaskWorker
taskWorker
=
new
TaskWorker
(
task
);
taskWorker
.
init
();
taskQueueExecutor
.
execute
(
taskWorker
);
taskQueueExecutor
.
execute
(()
->
{
taskWorker
.
init
();
taskWorker
.
run
();
});
return
taskWorker
;
}
...
...
@@ -52,6 +54,14 @@ public class BackgroundExecutor {
}
}
public
void
execute
(
String
title
,
List
<
Runnable
>
backgroundJobs
,
Runnable
onFinishUiRunnable
)
{
execute
(
new
SimpleTask
(
title
,
backgroundJobs
,
onFinishUiRunnable
));
}
public
void
execute
(
String
title
,
List
<
Runnable
>
backgroundJobs
)
{
execute
(
new
SimpleTask
(
title
,
backgroundJobs
,
null
));
}
public
void
execute
(
String
title
,
Runnable
backgroundRunnable
,
Runnable
onFinishUiRunnable
)
{
execute
(
new
SimpleTask
(
title
,
backgroundRunnable
,
onFinishUiRunnable
));
}
...
...
@@ -85,6 +95,7 @@ public class BackgroundExecutor {
List
<
Runnable
>
jobs
=
task
.
scheduleJobs
();
jobsCount
=
jobs
.
size
();
LOG
.
debug
(
"Starting background task '{}', jobs count: {}"
,
task
.
getTitle
(),
jobsCount
);
if
(
jobsCount
==
1
)
{
jobs
.
get
(
0
).
run
();
return
true
;
...
...
@@ -149,15 +160,19 @@ public class BackgroundExecutor {
private
static
final
class
SimpleTask
implements
IBackgroundTask
{
private
final
String
title
;
private
final
Runnable
runnable
;
private
final
List
<
Runnable
>
jobs
;
private
final
Runnable
onFinish
;
public
SimpleTask
(
String
title
,
Runnable
runnable
,
@Nullable
Runnable
onFinish
)
{
public
SimpleTask
(
String
title
,
List
<
Runnable
>
jobs
,
@Nullable
Runnable
onFinish
)
{
this
.
title
=
title
;
this
.
runnable
=
runnable
;
this
.
jobs
=
jobs
;
this
.
onFinish
=
onFinish
;
}
public
SimpleTask
(
String
title
,
Runnable
job
,
@Nullable
Runnable
onFinish
)
{
this
(
title
,
Collections
.
singletonList
(
job
),
onFinish
);
}
@Override
public
String
getTitle
()
{
return
title
;
...
...
@@ -165,7 +180,7 @@ public class BackgroundExecutor {
@Override
public
List
<
Runnable
>
scheduleJobs
()
{
return
Collections
.
singletonList
(
runnable
)
;
return
jobs
;
}
@Override
...
...
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundWorker.java
浏览文件 @
ae265126
...
...
@@ -54,23 +54,6 @@ public class BackgroundWorker extends SwingWorker<Void, Void> {
runJob
(
cache
.
getDecompileJob
());
LOG
.
debug
(
"Memory usage: After decompile: {}"
,
UiUtils
.
memoryInfo
());
if
(
cache
.
getUnloadJob
()
!=
null
)
{
LOG
.
info
(
"Memory usage: Before unload: {}"
,
UiUtils
.
memoryInfo
());
long
start
=
System
.
nanoTime
();
runJob
(
cache
.
getUnloadJob
());
cache
.
setUnloadJob
(
null
);
LOG
.
info
(
"Memory usage: After unload: {}, unload took {} ms"
,
UiUtils
.
memoryInfo
(),
(
System
.
nanoTime
()
-
start
)
/
1000000
);
}
if
(
cache
.
getRefreshJob
()
!=
null
)
{
LOG
.
info
(
"Memory usage: Before refresh: {}"
,
UiUtils
.
memoryInfo
());
long
start
=
System
.
nanoTime
();
runJob
(
cache
.
getRefreshJob
());
cache
.
setRefreshJob
(
null
);
LOG
.
info
(
"Memory usage: After refresh: {}, refresh took {} ms"
,
UiUtils
.
memoryInfo
(),
(
System
.
nanoTime
()
-
start
)
/
1000000
);
}
LOG
.
debug
(
"Memory usage: Before index: {}"
,
UiUtils
.
memoryInfo
());
runJob
(
cache
.
getIndexJob
());
LOG
.
debug
(
"Memory usage: After index: {}"
,
UiUtils
.
memoryInfo
());
...
...
jadx-gui/src/main/java/jadx/gui/jobs/IndexJob.java
浏览文件 @
ae265126
...
...
@@ -31,33 +31,53 @@ public class IndexJob extends BackgroundJob {
@Override
protected
void
runJob
()
{
JNodeCache
nodeCache
=
cache
.
getNodeCache
();
final
TextSearchIndex
index
=
new
TextSearchIndex
(
nodeCache
);
final
CodeUsageInfo
usageInfo
=
new
CodeUsageInfo
(
nodeCache
);
TextSearchIndex
index
=
new
TextSearchIndex
(
nodeCache
);
CodeUsageInfo
usageInfo
=
new
CodeUsageInfo
(
nodeCache
);
cache
.
setTextIndex
(
index
);
cache
.
setUsageInfo
(
usageInfo
);
for
(
final
JavaClass
cls
:
wrapper
.
getIncludedClasses
())
{
addTask
(()
->
{
try
{
index
.
indexNames
(
cls
);
addTask
(()
->
indexCls
(
cache
,
cls
));
}
}
public
static
void
indexCls
(
CacheObject
cache
,
JavaClass
cls
)
{
try
{
TextSearchIndex
index
=
cache
.
getTextIndex
();
CodeUsageInfo
usageInfo
=
cache
.
getUsageInfo
();
if
(
index
==
null
||
usageInfo
==
null
)
{
return
;
}
CodeLinesInfo
linesInfo
=
new
CodeLinesInfo
(
cls
);
List
<
StringRef
>
lines
=
splitLines
(
cls
);
index
.
indexNames
(
cls
);
CodeLinesInfo
linesInfo
=
new
CodeLinesInfo
(
cls
);
List
<
StringRef
>
lines
=
splitLines
(
cls
);
usageInfo
.
processClass
(
cls
,
linesInfo
,
lines
);
if
(
UiUtils
.
isFreeMemoryAvailable
())
{
index
.
indexCode
(
cls
,
linesInfo
,
lines
);
}
else
{
index
.
classCodeIndexSkipped
(
cls
);
}
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Index error in class: {}"
,
cls
.
getFullName
(),
e
);
}
}
usageInfo
.
processClass
(
cls
,
linesInfo
,
lines
);
if
(
UiUtils
.
isFreeMemoryAvailable
())
{
index
.
indexCode
(
cls
,
linesInfo
,
lines
);
}
else
{
index
.
classCodeIndexSkipped
(
cls
);
}
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Index error in class: {}"
,
cls
.
getFullName
(),
e
);
}
});
public
static
void
refreshIndex
(
CacheObject
cache
,
JavaClass
cls
)
{
TextSearchIndex
index
=
cache
.
getTextIndex
();
CodeUsageInfo
usageInfo
=
cache
.
getUsageInfo
();
if
(
index
==
null
||
usageInfo
==
null
)
{
return
;
}
index
.
remove
(
cls
);
usageInfo
.
remove
(
cls
);
indexCls
(
cache
,
cls
);
}
@NotNull
protected
List
<
StringRef
>
splitLines
(
JavaClass
cls
)
{
protected
static
List
<
StringRef
>
splitLines
(
JavaClass
cls
)
{
List
<
StringRef
>
lines
=
StringRef
.
split
(
cls
.
getCode
(),
CodeWriter
.
NL
);
int
size
=
lines
.
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
...
...
jadx-gui/src/main/java/jadx/gui/jobs/RefreshJob.java
已删除
100644 → 0
浏览文件 @
498c2f52
package
jadx.gui.jobs
;
import
java.util.Set
;
import
jadx.api.JavaClass
;
import
jadx.gui.JadxWrapper
;
public
class
RefreshJob
extends
BackgroundJob
{
private
Set
<
JavaClass
>
refreshClasses
;
public
RefreshJob
(
JadxWrapper
jadxWrapper
,
int
threadsCount
,
Set
<
JavaClass
>
refreshClasses
)
{
super
(
jadxWrapper
,
threadsCount
);
this
.
refreshClasses
=
refreshClasses
;
}
protected
void
runJob
()
{
for
(
final
JavaClass
cls
:
refreshClasses
)
{
addTask
(
cls:
:
refresh
);
}
}
@Override
public
String
getInfoString
()
{
return
"Refreshing: "
;
}
}
jadx-gui/src/main/java/jadx/gui/jobs/UnloadJob.java
已删除
100644 → 0
浏览文件 @
498c2f52
package
jadx.gui.jobs
;
import
java.util.Set
;
import
jadx.api.JavaClass
;
import
jadx.gui.JadxWrapper
;
public
class
UnloadJob
extends
BackgroundJob
{
private
Set
<
JavaClass
>
refreshClasses
;
public
UnloadJob
(
JadxWrapper
jadxWrapper
,
int
threadsCount
,
Set
<
JavaClass
>
refreshClasses
)
{
super
(
jadxWrapper
,
threadsCount
);
this
.
refreshClasses
=
refreshClasses
;
}
protected
void
runJob
()
{
for
(
final
JavaClass
cls
:
refreshClasses
)
{
addTask
(()
->
{
cls
.
unload
();
cls
.
getClassNode
().
deepUnload
();
});
}
}
@Override
public
String
getInfoString
()
{
return
"Refreshing: "
;
}
}
jadx-gui/src/main/java/jadx/gui/treemodel/CodeNode.java
浏览文件 @
ae265126
...
...
@@ -48,6 +48,10 @@ public class CodeNode extends JNode {
return
null
;
}
public
StringRef
getLineStr
()
{
return
line
;
}
@Override
public
int
getLine
()
{
return
lineNum
;
...
...
@@ -72,4 +76,21 @@ public class CodeNode extends JNode {
public
String
makeLongString
()
{
return
makeString
();
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
{
return
true
;
}
if
(!(
o
instanceof
CodeNode
))
{
return
false
;
}
CodeNode
codeNode
=
(
CodeNode
)
o
;
return
jNode
.
equals
(
codeNode
.
jNode
);
}
@Override
public
int
hashCode
()
{
return
jNode
.
hashCode
();
}
}
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
浏览文件 @
ae265126
...
...
@@ -415,12 +415,6 @@ public class MainWindow extends JFrame {
}
}
synchronized
void
runBackgroundUnloadRefreshAndIndexJobs
()
{
cancelBackgroundJobs
();
backgroundWorker
=
new
BackgroundWorker
(
cacheObject
,
progressPane
);
backgroundWorker
.
exec
();
}
public
synchronized
void
cancelBackgroundJobs
()
{
backgroundExecutor
.
cancelAll
();
if
(
backgroundWorker
!=
null
)
{
...
...
@@ -520,7 +514,7 @@ public class MainWindow extends JFrame {
tabbedPane
.
closeAllTabs
();
resetCache
();
treeRoot
=
null
;
treeModel
.
setRoot
(
treeRoot
);
treeModel
.
setRoot
(
null
);
treeModel
.
reload
();
}
...
...
@@ -1136,6 +1130,10 @@ public class MainWindow extends JFrame {
return
backgroundWorker
;
}
public
BackgroundExecutor
getBackgroundExecutor
()
{
return
backgroundExecutor
;
}
public
ProgressPanel
getProgressPane
()
{
return
progressPane
;
}
...
...
jadx-gui/src/main/java/jadx/gui/ui/RenameDialog.java
浏览文件 @
ae265126
...
...
@@ -8,10 +8,10 @@ import java.nio.charset.StandardCharsets;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.StandardCopyOption
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
javax.swing.*
;
...
...
@@ -23,11 +23,11 @@ import jadx.api.JavaClass;
import
jadx.api.JavaField
;
import
jadx.api.JavaMethod
;
import
jadx.api.JavaNode
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.dex.visitors.RenameVisitor
;
import
jadx.core.utils.Utils
;
import
jadx.gui.jobs.IndexJob
;
import
jadx.gui.jobs.RefreshJob
;
import
jadx.gui.jobs.UnloadJob
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JField
;
...
...
@@ -37,77 +37,59 @@ import jadx.gui.treemodel.JPackage;
import
jadx.gui.ui.codearea.ClassCodeContentPanel
;
import
jadx.gui.ui.codearea.CodeArea
;
import
jadx.gui.ui.codearea.CodePanel
;
import
jadx.gui.utils.*
;
import
jadx.gui.utils.CacheObject
;
import
jadx.gui.utils.JNodeCache
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.TextStandardActions
;
public
class
RenameDialog
extends
CommonSearch
Dialog
{
public
class
RenameDialog
extends
J
Dialog
{
private
static
final
long
serialVersionUID
=
-
3269715644416902410L
;
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
RenameDialog
.
class
);
pr
otected
final
transient
MainWindow
mainWindow
;
pr
ivate
final
transient
MainWindow
mainWindow
;
private
final
transient
CacheObject
cache
;
private
final
transient
JNode
node
;
private
JTextField
renameField
;
private
CodeArea
codeArea
;
private
JButton
renameBtn
;
private
transient
JTextField
renameField
;
public
RenameDialog
(
CodeArea
codeArea
,
JNode
node
)
{
super
(
codeArea
.
getMainWindow
());
mainWindow
=
codeArea
.
getMainWindow
();
this
.
c
odeArea
=
codeArea
;
this
.
mainWindow
=
codeArea
.
getMainWindow
();
this
.
c
ache
=
mainWindow
.
getCacheObject
()
;
this
.
node
=
node
;
if
(
isDeobfuscationSettingsValid
())
{
if
(
checkSettings
())
{
initUI
();
registerInitOnOpen
();
loadWindowPos
();
}
else
{
LOG
.
error
(
"Deobfuscation settings are invalid - please enable deobfuscation and disable force rewrite deobfuscation map"
);
}
}
private
boolean
isDeobfuscationSettingsValid
()
{
boolean
valid
=
true
;
String
errorMessage
=
null
;
private
boolean
checkSettings
()
{
StringBuilder
errorMessage
=
new
StringBuilder
();
errorMessage
.
append
(
NLS
.
str
(
"msg.rename_disabled"
)).
append
(
CodeWriter
.
NL
);
JadxSettings
settings
=
mainWindow
.
getSettings
();
final
LangLocale
langLocale
=
settings
.
getLangLocale
();
if
(
settings
.
isDeobfuscationForceSave
())
{
boolean
valid
=
true
;
if
(!
settings
.
isDeobfuscationOn
())
{
errorMessage
.
append
(
" - "
).
append
(
NLS
.
str
(
"msg.rename_disabled_deobfuscation_disabled"
)).
append
(
CodeWriter
.
NL
);
valid
=
false
;
errorMessage
=
NLS
.
str
(
"msg.rename_disabled_force_rewrite_enabled"
,
langLocale
);
}
if
(!
settings
.
isDeobfuscationOn
())
{
if
(
settings
.
isDeobfuscationForceSave
())
{
errorMessage
.
append
(
" - "
).
append
(
NLS
.
str
(
"msg.rename_disabled_force_rewrite_enabled"
)).
append
(
CodeWriter
.
NL
);
valid
=
false
;
errorMessage
=
NLS
.
str
(
"msg.rename_disabled_deobfuscation_disabled"
,
langLocale
);
}
if
(
errorMessage
!=
null
)
{
showRenameDisabledErrorMessage
(
langLocale
,
errorMessage
)
;
if
(
valid
)
{
return
true
;
}
return
valid
;
}
private
void
showRenameDisabledErrorMessage
(
LangLocale
langLocale
,
String
message
)
{
JOptionPane
.
showMessageDialog
(
mainWindow
,
message
,
NLS
.
str
(
"msg.rename_disabled_title"
,
langLocale
),
JOptionPane
.
ERROR_MESSAGE
);
}
@Override
protected
void
openInit
()
{
prepare
();
}
@Override
protected
void
loadStart
()
{
renameBtn
.
setEnabled
(
false
);
}
int
result
=
JOptionPane
.
showConfirmDialog
(
mainWindow
,
errorMessage
.
toString
(),
NLS
.
str
(
"msg.rename_disabled_title"
),
JOptionPane
.
OK_CANCEL_OPTION
);
if
(
result
!=
JOptionPane
.
OK_OPTION
)
{
return
false
;
}
settings
.
setDeobfuscationOn
(
true
);
settings
.
setDeobfuscationForceSave
(
false
);
settings
.
sync
();
@Override
protected
void
loadFinished
()
{
renameBtn
.
setEnabled
(
true
);
mainWindow
.
reOpenFile
();
return
false
;
// TODO: can't open dialog, 'node' is replaced with new one after reopen
}
private
Path
getDeobfMapPath
(
RootNode
root
)
{
...
...
@@ -195,29 +177,26 @@ public class RenameDialog extends CommonSearchDialog {
}
private
void
rename
()
{
long
start
=
System
.
nanoTime
();
String
renameText
=
renameField
.
getText
();
if
(
renameText
==
null
||
renameText
.
length
()
==
0
||
codeArea
.
getText
()
==
null
)
{
return
;
}
RootNode
root
=
mainWindow
.
getWrapper
().
getDecompiler
().
getRoot
();
if
(
node
==
null
)
{
LOG
.
error
(
"rename(): rootNode is null!"
);
dispose
();
return
;
}
if
(!
refreshDeobfMapFile
(
renameText
,
root
))
{
LOG
.
error
(
"rename(): refreshDeobfMapFile() failed!"
);
dispose
();
return
;
try
{
String
renameText
=
renameField
.
getText
();
if
(
renameText
==
null
||
renameText
.
length
()
==
0
)
{
return
;
}
RootNode
root
=
mainWindow
.
getWrapper
().
getDecompiler
().
getRoot
();
if
(
node
==
null
)
{
LOG
.
error
(
"rename(): rootNode is null!"
);
dispose
();
return
;
}
if
(!
refreshDeobfMapFile
(
renameText
,
root
))
{
LOG
.
error
(
"rename(): refreshDeobfMapFile() failed!"
);
dispose
();
return
;
}
refreshState
(
root
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Rename failed"
,
e
);
}
long
refreshStart
=
System
.
nanoTime
();
int
classes
=
refreshState
(
root
);
long
refreshTime
=
(
System
.
nanoTime
()
-
refreshStart
)
/
1000000
;
long
totalTime
=
(
System
.
nanoTime
()
-
start
)
/
1000000
;
LOG
.
info
(
"refreshState() took {} ms to update state, {} classes will be refreshed in background ({} ms total)"
,
refreshTime
,
classes
,
totalTime
);
dispose
();
}
...
...
@@ -240,92 +219,60 @@ public class RenameDialog extends CommonSearchDialog {
return
true
;
}
private
int
refreshState
(
RootNode
rootNode
)
{
private
void
refreshState
(
RootNode
rootNode
)
{
RenameVisitor
renameVisitor
=
new
RenameVisitor
();
renameVisitor
.
init
(
rootNode
);
cache
.
getNodeCache
().
refresh
(
node
);
Set
<
JavaClass
>
updatedClasses
=
getUpdatedClasses
();
JNodeCache
nodeCache
=
cache
.
getNodeCache
();
Set
<
JClass
>
updatedClasses
=
node
.
getJavaNode
().
getUseIn
()
.
stream
()
.
map
(
nodeCache:
:
makeFrom
)
.
map
(
JNode:
:
getRootClass
)
.
collect
(
Collectors
.
toSet
());
updatedClasses
.
add
(
node
.
getRootClass
());
mainWindow
.
reloadTree
();
refreshTabs
(
mainWindow
.
getTabbedPane
(),
updatedClasses
);
if
(
updatedClasses
.
size
()
>
0
)
{
setRefreshTask
(
updatedClasses
);
if
(!
updatedClasses
.
isEmpty
())
{
mainWindow
.
getBackgroundExecutor
().
execute
(
"Refreshing"
,
Utils
.
collectionMap
(
updatedClasses
,
cls
->
()
->
refreshJClass
(
cls
)),
mainWindow:
:
reloadTree
);
}
}
return
updatedClasses
.
size
();
private
void
refreshJClass
(
JClass
cls
)
{
cls
.
refresh
();
IndexJob
.
refreshIndex
(
cache
,
cls
.
getCls
());
}
private
void
refreshTabs
(
TabbedPane
tabbedPane
,
Set
<
J
ava
Class
>
updatedClasses
)
{
for
(
Map
.
Entry
<
JNode
,
ContentPanel
>
panel
:
tabbedPane
.
getOpenTabs
().
entrySet
())
{
ContentPanel
contentPanel
=
panel
.
getValue
();
private
void
refreshTabs
(
TabbedPane
tabbedPane
,
Set
<
JClass
>
updatedClasses
)
{
for
(
Map
.
Entry
<
JNode
,
ContentPanel
>
entry
:
tabbedPane
.
getOpenTabs
().
entrySet
())
{
ContentPanel
contentPanel
=
entry
.
getValue
();
if
(
contentPanel
instanceof
ClassCodeContentPanel
)
{
JNode
node
=
panel
.
getKey
();
JNode
node
=
entry
.
getKey
();
JClass
rootClass
=
node
.
getRootClass
();
JavaClass
javaClass
=
rootClass
.
getCls
();
if
(
updatedClasses
.
contains
(
javaClass
)
||
node
.
getRootClass
().
getCls
()
==
javaClass
)
{
LOG
.
info
(
"Refreshing rootClass "
+
javaClass
.
getRawName
());
javaClass
.
unload
();
javaClass
.
getClassNode
().
deepUnload
();
rootClass
.
refresh
();
// Update code cache
if
(
updatedClasses
.
contains
(
rootClass
))
{
refreshJClass
(
rootClass
);
ClassCodeContentPanel
codePanel
=
(
ClassCodeContentPanel
)
contentPanel
;
CodePanel
javaPanel
=
codePanel
.
getJavaCodePanel
();
javaPanel
.
refresh
();
tabbedPane
.
refresh
(
node
);
updatedClasses
.
remove
(
javaClass
);
tabbedPane
.
refresh
(
rootClass
);
}
}
}
}
private
Set
<
JavaClass
>
getUpdatedClasses
()
{
Set
<
JavaClass
>
usageClasses
=
new
HashSet
<>();
CodeUsageInfo
usageInfo
=
cache
.
getUsageInfo
();
if
(
usageInfo
!=
null
)
{
usageInfo
.
getUsageList
(
node
).
forEach
((
node
)
->
{
JavaClass
rootClass
=
node
.
getRootClass
().
getCls
();
// LOG.info("updateUsages(): Going to update class {}", rootClass.getRealFullName());
usageClasses
.
add
(
rootClass
);
});
// usageClasses.parallelStream().forEach(JavaClass::refresh);
}
return
usageClasses
;
}
private
void
setRefreshTask
(
Set
<
JavaClass
>
refreshClasses
)
{
UnloadJob
unloadJob
=
new
UnloadJob
(
mainWindow
.
getWrapper
(),
mainWindow
.
getSettings
().
getThreadsCount
(),
refreshClasses
);
RefreshJob
refreshJob
=
new
RefreshJob
(
mainWindow
.
getWrapper
(),
mainWindow
.
getSettings
().
getThreadsCount
(),
refreshClasses
);
LOG
.
info
(
"Waiting for old unloadJob and refreshJob"
);
while
(
cache
.
getUnloadJob
()
!=
null
||
cache
.
getRefreshJob
()
!=
null
)
{
try
{
Thread
.
sleep
(
10
);
}
catch
(
InterruptedException
e
)
{
return
;
}
}
LOG
.
info
(
"Old unloadJob and refreshJob finished"
);
cache
.
setUnloadJob
(
unloadJob
);
cache
.
setRefreshJob
(
refreshJob
);
cache
.
setIndexJob
(
new
IndexJob
(
mainWindow
.
getWrapper
(),
cache
,
mainWindow
.
getSettings
().
getThreadsCount
()));
mainWindow
.
runBackgroundUnloadRefreshAndIndexJobs
();
}
@NotNull
protected
JPanel
initButtonsPanel
()
{
JButton
cancelButton
=
new
JButton
(
NLS
.
str
(
"search_dialog.cancel"
));
cancelButton
.
addActionListener
(
event
->
dispose
());
renameBtn
=
new
JButton
(
NLS
.
str
(
"popup.rename"
));
JButton
renameBtn
=
new
JButton
(
NLS
.
str
(
"popup.rename"
));
renameBtn
.
addActionListener
(
event
->
rename
());
getRootPane
().
setDefaultButton
(
renameBtn
);
progressPane
=
new
ProgressPanel
(
mainWindow
,
false
);
JPanel
buttonPane
=
new
JPanel
();
buttonPane
.
setLayout
(
new
BoxLayout
(
buttonPane
,
BoxLayout
.
LINE_AXIS
));
buttonPane
.
setBorder
(
BorderFactory
.
createEmptyBorder
(
0
,
10
,
10
,
10
));
buttonPane
.
add
(
progressPane
);
buttonPane
.
add
(
Box
.
createRigidArea
(
new
Dimension
(
5
,
0
)));
buttonPane
.
add
(
Box
.
createHorizontalGlue
());
buttonPane
.
add
(
renameBtn
);
...
...
@@ -351,18 +298,12 @@ public class RenameDialog extends CommonSearchDialog {
renamePane
.
add
(
nodeLabel
);
renamePane
.
setBorder
(
BorderFactory
.
createEmptyBorder
(
10
,
10
,
10
,
10
));
warnLabel
=
new
JLabel
();
warnLabel
.
setForeground
(
Color
.
RED
);
warnLabel
.
setVisible
(
false
);
JPanel
textPane
=
new
JPanel
();
textPane
.
setLayout
(
new
BoxLayout
(
textPane
,
BoxLayout
.
PAGE_AXIS
));
textPane
.
add
(
warnLabel
);
textPane
.
add
(
Box
.
createRigidArea
(
new
Dimension
(
0
,
5
)));
textPane
.
add
(
renameField
);
textPane
.
setBorder
(
BorderFactory
.
createEmptyBorder
(
10
,
10
,
10
,
10
));
initCommon
();
JPanel
buttonPane
=
initButtonsPanel
();
Container
contentPane
=
getContentPane
();
...
...
@@ -376,5 +317,7 @@ public class RenameDialog extends CommonSearchDialog {
setLocationRelativeTo
(
null
);
setDefaultCloseOperation
(
WindowConstants
.
DISPOSE_ON_CLOSE
);
setModalityType
(
ModalityType
.
MODELESS
);
mainWindow
.
getSettings
().
loadWindowPos
(
this
);
}
}
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
浏览文件 @
ae265126
...
...
@@ -7,8 +7,6 @@ import org.jetbrains.annotations.Nullable;
import
jadx.gui.jobs.DecompileJob
;
import
jadx.gui.jobs.IndexJob
;
import
jadx.gui.jobs.RefreshJob
;
import
jadx.gui.jobs.UnloadJob
;
import
jadx.gui.ui.SearchDialog
;
import
jadx.gui.utils.search.TextSearchIndex
;
...
...
@@ -16,8 +14,6 @@ public class CacheObject {
private
DecompileJob
decompileJob
;
private
IndexJob
indexJob
;
private
UnloadJob
unloadJob
;
private
RefreshJob
refreshJob
;
private
TextSearchIndex
textIndex
;
private
CodeUsageInfo
usageInfo
;
...
...
@@ -93,20 +89,4 @@ public class CacheObject {
public
Set
<
SearchDialog
.
SearchOptions
>
getLastSearchOptions
()
{
return
lastSearchOptions
;
}
public
RefreshJob
getRefreshJob
()
{
return
refreshJob
;
}
public
void
setRefreshJob
(
RefreshJob
refreshJob
)
{
this
.
refreshJob
=
refreshJob
;
}
public
UnloadJob
getUnloadJob
()
{
return
unloadJob
;
}
public
void
setUnloadJob
(
UnloadJob
unloadJob
)
{
this
.
unloadJob
=
unloadJob
;
}
}
jadx-gui/src/main/java/jadx/gui/utils/CodeUsageInfo.java
浏览文件 @
ae265126
...
...
@@ -70,4 +70,14 @@ public class CodeUsageInfo {
}
return
usageInfo
.
getUsageList
();
}
public
void
remove
(
JavaClass
cls
)
{
usageMap
.
entrySet
().
removeIf
(
e
->
{
if
(
e
.
getKey
().
getJavaNode
().
getTopParentClass
().
equals
(
cls
))
{
return
true
;
}
e
.
getValue
().
getUsageList
().
removeIf
(
node
->
node
.
getJavaNode
().
getTopParentClass
().
equals
(
cls
));
return
false
;
});
}
}
jadx-gui/src/main/java/jadx/gui/utils/JNodeCache.java
浏览文件 @
ae265126
...
...
@@ -29,12 +29,6 @@ public class JNodeCache {
return
jNode
;
}
public
void
refresh
(
JNode
node
)
{
JavaNode
javaNode
=
node
.
getJavaNode
();
cache
.
remove
(
javaNode
);
makeFrom
(
javaNode
);
}
private
JNode
convert
(
JavaNode
node
)
{
if
(
node
==
null
)
{
return
null
;
...
...
jadx-gui/src/main/java/jadx/gui/utils/search/CodeIndex.java
浏览文件 @
ae265126
...
...
@@ -9,46 +9,34 @@ import org.slf4j.LoggerFactory;
import
io.reactivex.BackpressureStrategy
;
import
io.reactivex.Flowable
;
import
jadx.api.JavaClass
;
import
jadx.gui.treemodel.CodeNode
;
import
jadx.gui.utils.UiUtils
;
public
class
CodeIndex
<
T
>
implements
SearchIndex
<
T
>
{
public
class
CodeIndex
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
CodeIndex
.
class
);
private
final
List
<
StringRef
>
keys
=
new
ArrayList
<>();
private
final
List
<
T
>
values
=
new
ArrayList
<>();
private
final
List
<
CodeNode
>
values
=
new
ArrayList
<>();
@Override
public
void
put
(
String
str
,
T
value
)
{
throw
new
UnsupportedOperationException
(
"CodeIndex.put for string not supported"
);
}
@Override
public
synchronized
void
put
(
StringRef
str
,
T
value
)
{
if
(
str
==
null
||
str
.
length
()
==
0
)
{
return
;
}
keys
.
add
(
str
);
public
synchronized
void
put
(
CodeNode
value
)
{
values
.
add
(
value
);
}
@Override
public
boolean
isStringRefSupported
()
{
return
true
;
public
void
removeForCls
(
JavaClass
cls
)
{
values
.
removeIf
(
v
->
v
.
getJavaNode
().
getTopParentClass
().
equals
(
cls
));
}
private
boolean
isMatched
(
StringRef
key
,
String
str
,
boolean
caseInsensitive
)
{
return
key
.
indexOf
(
str
,
caseInsensitive
)
!=
-
1
;
}
@Override
public
Flowable
<
T
>
search
(
final
String
searchStr
,
final
boolean
caseInsensitive
)
{
public
Flowable
<
CodeNode
>
search
(
final
String
searchStr
,
final
boolean
caseInsensitive
)
{
return
Flowable
.
create
(
emitter
->
{
int
size
=
size
();
LOG
.
debug
(
"Code search started: {} ..."
,
searchStr
);
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
if
(
isMatched
(
keys
.
get
(
i
),
searchStr
,
caseInsensitive
))
{
emitter
.
onNext
(
values
.
get
(
i
)
);
for
(
CodeNode
node
:
values
)
{
if
(
isMatched
(
node
.
getLineStr
(
),
searchStr
,
caseInsensitive
))
{
emitter
.
onNext
(
node
);
}
if
(
emitter
.
isCancelled
())
{
LOG
.
debug
(
"Code search canceled: {}"
,
searchStr
);
...
...
@@ -60,8 +48,7 @@ public class CodeIndex<T> implements SearchIndex<T> {
},
BackpressureStrategy
.
LATEST
);
}
@Override
public
int
size
()
{
return
key
s
.
size
();
return
value
s
.
size
();
}
}
jadx-gui/src/main/java/jadx/gui/utils/search/SearchIndex.java
浏览文件 @
ae265126
...
...
@@ -6,10 +6,6 @@ public interface SearchIndex<V> {
void
put
(
String
str
,
V
value
);
void
put
(
StringRef
str
,
V
value
);
boolean
isStringRefSupported
();
Flowable
<
V
>
search
(
String
searchStr
,
boolean
caseInsensitive
);
int
size
();
...
...
jadx-gui/src/main/java/jadx/gui/utils/search/SimpleIndex.java
浏览文件 @
ae265126
package
jadx.gui.utils.search
;
import
java.util.
ArrayList
;
import
java.util.
List
;
import
java.util.
Map
;
import
java.util.
concurrent.ConcurrentHashMap
;
import
org.apache.commons.lang3.StringUtils
;
import
io.reactivex.BackpressureStrategy
;
import
io.reactivex.Flowable
;
public
class
SimpleIndex
<
T
>
implements
SearchIndex
<
T
>
{
import
jadx.api.JavaClass
;
import
jadx.gui.treemodel.JNode
;
private
final
List
<
String
>
keys
=
new
ArrayList
<>();
private
final
List
<
T
>
values
=
new
ArrayList
<>();
public
class
SimpleIndex
{
private
final
Map
<
JNode
,
String
>
data
=
new
ConcurrentHashMap
<>();
private
final
Object
syncData
=
new
Object
();
@Override
public
void
put
(
String
str
,
T
value
)
{
synchronized
(
syncData
)
{
keys
.
add
(
str
);
values
.
add
(
value
);
}
}
@Override
public
void
put
(
StringRef
str
,
T
value
)
{
throw
new
UnsupportedOperationException
(
"StringRef not supported"
);
public
void
put
(
String
str
,
JNode
value
)
{
data
.
put
(
value
,
str
);
}
@Override
public
boolean
isStringRefSupported
()
{
return
false
;
public
void
removeForCls
(
JavaClass
cls
)
{
data
.
entrySet
().
removeIf
(
e
->
e
.
getKey
().
getJavaNode
().
getTopParentClass
().
equals
(
cls
));
}
private
boolean
isMatched
(
String
str
,
String
searchStr
,
boolean
caseInsensitive
)
{
...
...
@@ -41,28 +30,22 @@ public class SimpleIndex<T> implements SearchIndex<T> {
}
}
@Override
public
Flowable
<
T
>
search
(
final
String
searchStr
,
final
boolean
caseInsensitive
)
{
public
Flowable
<
JNode
>
search
(
final
String
searchStr
,
final
boolean
caseInsensitive
)
{
return
Flowable
.
create
(
emitter
->
{
synchronized
(
syncData
)
{
int
size
=
keys
.
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
(
isMatched
(
keys
.
get
(
i
),
searchStr
,
caseInsensitive
))
{
emitter
.
onNext
(
values
.
get
(
i
));
}
if
(
emitter
.
isCancelled
())
{
return
;
}
for
(
Map
.
Entry
<
JNode
,
String
>
entry
:
data
.
entrySet
())
{
if
(
isMatched
(
entry
.
getValue
(),
searchStr
,
caseInsensitive
))
{
emitter
.
onNext
(
entry
.
getKey
());
}
if
(
emitter
.
isCancelled
())
{
return
;
}
}
emitter
.
onComplete
();
},
BackpressureStrategy
.
LATEST
);
}
@Override
public
int
size
()
{
synchronized
(
syncData
)
{
return
keys
.
size
();
}
return
data
.
size
();
}
}
jadx-gui/src/main/java/jadx/gui/utils/search/TextSearchIndex.java
浏览文件 @
ae265126
...
...
@@ -36,19 +36,19 @@ public class TextSearchIndex {
private
final
JNodeCache
nodeCache
;
private
SearchIndex
<
JNode
>
clsNamesIndex
;
private
SearchIndex
<
JNode
>
mthSignaturesIndex
;
private
SearchIndex
<
JNode
>
fldSignaturesIndex
;
private
SearchIndex
<
CodeNode
>
codeIndex
;
private
final
SimpleIndex
clsNamesIndex
;
private
final
SimpleIndex
mthSignaturesIndex
;
private
final
SimpleIndex
fldSignaturesIndex
;
private
final
CodeIndex
codeIndex
;
private
List
<
JavaClass
>
skippedClasses
=
new
ArrayList
<>();
private
final
List
<
JavaClass
>
skippedClasses
=
new
ArrayList
<>();
public
TextSearchIndex
(
JNodeCache
nodeCache
)
{
this
.
nodeCache
=
nodeCache
;
this
.
clsNamesIndex
=
new
SimpleIndex
<>
();
this
.
mthSignaturesIndex
=
new
SimpleIndex
<>
();
this
.
fldSignaturesIndex
=
new
SimpleIndex
<>
();
this
.
codeIndex
=
new
CodeIndex
<>
();
this
.
clsNamesIndex
=
new
SimpleIndex
();
this
.
mthSignaturesIndex
=
new
SimpleIndex
();
this
.
fldSignaturesIndex
=
new
SimpleIndex
();
this
.
codeIndex
=
new
CodeIndex
();
}
public
void
indexNames
(
JavaClass
cls
)
{
...
...
@@ -68,7 +68,6 @@ public class TextSearchIndex {
public
void
indexCode
(
JavaClass
cls
,
CodeLinesInfo
linesInfo
,
List
<
StringRef
>
lines
)
{
try
{
boolean
strRefSupported
=
codeIndex
.
isStringRefSupported
();
int
count
=
lines
.
size
();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
StringRef
line
=
lines
.
get
(
i
);
...
...
@@ -78,18 +77,21 @@ public class TextSearchIndex {
}
int
lineNum
=
i
+
1
;
JavaNode
node
=
linesInfo
.
getJavaNodeByLine
(
lineNum
);
CodeNode
codeNode
=
new
CodeNode
(
nodeCache
.
makeFrom
(
node
==
null
?
cls
:
node
),
lineNum
,
line
);
if
(
strRefSupported
)
{
codeIndex
.
put
(
line
,
codeNode
);
}
else
{
codeIndex
.
put
(
line
.
toString
(),
codeNode
);
}
JNode
nodeAtLine
=
nodeCache
.
makeFrom
(
node
==
null
?
cls
:
node
);
codeIndex
.
put
(
new
CodeNode
(
nodeAtLine
,
lineNum
,
line
));
}
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"Failed to index class: {}"
,
cls
,
e
);
}
}
public
void
remove
(
JavaClass
cls
)
{
this
.
clsNamesIndex
.
removeForCls
(
cls
);
this
.
mthSignaturesIndex
.
removeForCls
(
cls
);
this
.
fldSignaturesIndex
.
removeForCls
(
cls
);
this
.
codeIndex
.
removeForCls
(
cls
);
}
public
Flowable
<
JNode
>
buildSearch
(
String
text
,
Set
<
SearchDialog
.
SearchOptions
>
options
)
{
boolean
ignoreCase
=
options
.
contains
(
IGNORE_CASE
);
LOG
.
debug
(
"Building search, ignoreCase: {}"
,
ignoreCase
);
...
...
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
浏览文件 @
ae265126
...
...
@@ -137,9 +137,9 @@ msg.index_not_initialized=Index not initialized, search will be disabled!
msg.project_error_title
=
Error
msg.project_error
=
Project could not be loaded
msg.rename_disabled_title
=
Rename disabled
msg.rename_disabled
=
Some of rename settings are disabled,
please take this into consideration
msg.rename_disabled_force_rewrite_enabled
=
Please disable "Force rewrite deobfuscation map file" option to rename
.
msg.rename_disabled_deobfuscation_disabled
=
Please enable deobfuscation to rename
.
msg.rename_disabled
=
Some of rename settings are disabled,
next options will be changed:
msg.rename_disabled_force_rewrite_enabled
=
Disable "Force rewrite deobfuscation map file" option
.
msg.rename_disabled_deobfuscation_disabled
=
Enable deobfuscation
.
msg.cmd_select_class_error
=
Failed to select the class
\n
%s
\n
The class does not exist.
popup.undo
=
Undo
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录