Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
keyescgm
jadx
提交
5d6b8272
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,体验更适合开发者的 AI 搜索 >>
未验证
提交
5d6b8272
编写于
3月 16, 2023
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(gui): search constant fields usage in all classes (#1801)
上级
78c976ad
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
140 addition
and
72 deletion
+140
-72
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
+14
-6
jadx-core/src/main/java/jadx/core/utils/DecompilerScheduler.java
...re/src/main/java/jadx/core/utils/DecompilerScheduler.java
+2
-0
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
+0
-9
jadx-gui/src/main/java/jadx/gui/jobs/DecompileTask.java
jadx-gui/src/main/java/jadx/gui/jobs/DecompileTask.java
+46
-3
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+11
-42
jadx-gui/src/main/java/jadx/gui/ui/dialog/UsageDialog.java
jadx-gui/src/main/java/jadx/gui/ui/dialog/UsageDialog.java
+41
-12
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
+11
-0
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
+1
-0
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
+1
-0
jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties
jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties
jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
+1
-0
jadx-gui/src/main/resources/icons/ui/runAll.svg
jadx-gui/src/main/resources/icons/ui/runAll.svg
+7
-0
未找到文件。
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
浏览文件 @
5d6b8272
...
...
@@ -82,14 +82,22 @@ public class ConstStorage {
return
;
}
for
(
FieldNode
f
:
staticFields
)
{
AccessInfo
accFlags
=
f
.
getAccessFlags
();
if
(
accFlags
.
isStatic
()
&&
accFlags
.
isFinal
())
{
EncodedValue
constVal
=
f
.
get
(
JadxAttrType
.
CONSTANT_VALUE
);
if
(
constVal
!=
null
&&
constVal
.
getValue
()
!=
null
)
{
addConstField
(
cls
,
f
,
constVal
.
getValue
(),
accFlags
.
isPublic
());
}
Object
value
=
getFieldConstValue
(
f
);
if
(
value
!=
null
)
{
addConstField
(
cls
,
f
,
value
,
f
.
getAccessFlags
().
isPublic
());
}
}
}
public
static
@Nullable
Object
getFieldConstValue
(
FieldNode
fld
)
{
AccessInfo
accFlags
=
fld
.
getAccessFlags
();
if
(
accFlags
.
isStatic
()
&&
accFlags
.
isFinal
())
{
EncodedValue
constVal
=
fld
.
get
(
JadxAttrType
.
CONSTANT_VALUE
);
if
(
constVal
!=
null
)
{
return
constVal
.
getValue
();
}
}
return
null
;
}
public
void
removeForClass
(
ClassNode
cls
)
{
...
...
jadx-core/src/main/java/jadx/core/utils/DecompilerScheduler.java
浏览文件 @
5d6b8272
...
...
@@ -139,11 +139,13 @@ public class DecompilerScheduler implements IDecompileScheduler {
}
private
void
dumpBatchesStats
(
List
<
JavaClass
>
classes
,
List
<
List
<
JavaClass
>>
result
,
List
<
DepInfo
>
deps
)
{
int
clsInBatches
=
result
.
stream
().
mapToInt
(
List:
:
size
).
sum
();
double
avg
=
result
.
stream
().
mapToInt
(
List:
:
size
).
average
().
orElse
(-
1
);
int
maxSingleDeps
=
classes
.
stream
().
mapToInt
(
JavaClass:
:
getTotalDepsCount
).
max
().
orElse
(-
1
);
int
maxSubDeps
=
deps
.
stream
().
mapToInt
(
DepInfo:
:
getDepsCount
).
max
().
orElse
(-
1
);
LOG
.
info
(
"Batches stats:"
+
"\n input classes: "
+
classes
.
size
()
+
",\n classes in batches: "
+
clsInBatches
+
",\n batches: "
+
result
.
size
()
+
",\n average batch size: "
+
String
.
format
(
"%.2f"
,
avg
)
+
",\n max single deps count: "
+
maxSingleDeps
...
...
jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java
浏览文件 @
5d6b8272
...
...
@@ -20,7 +20,6 @@ import javax.swing.SwingWorker;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.panel.ProgressPanel
;
...
...
@@ -60,14 +59,6 @@ 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
synchronized
void
cancelAll
()
{
try
{
taskRunning
.
values
().
forEach
(
Cancelable:
:
cancel
);
...
...
jadx-gui/src/main/java/jadx/gui/jobs/DecompileTask.java
浏览文件 @
5d6b8272
...
...
@@ -5,12 +5,15 @@ import java.util.Collections;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
javax.swing.JOptionPane
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.ICodeCache
;
import
jadx.api.JavaClass
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.UiUtils
;
...
...
@@ -23,14 +26,16 @@ public class DecompileTask extends CancelableBackgroundTask {
return
classCount
*
CLS_LIMIT
+
5000
;
}
private
final
MainWindow
mainWindow
;
private
final
JadxWrapper
wrapper
;
private
final
AtomicInteger
complete
=
new
AtomicInteger
(
0
);
private
int
expectedCompleteCount
;
private
ProcessResult
result
;
public
DecompileTask
(
JadxWrapper
wrapper
)
{
this
.
wrapper
=
wrapper
;
public
DecompileTask
(
MainWindow
mainWindow
)
{
this
.
mainWindow
=
mainWindow
;
this
.
wrapper
=
mainWindow
.
getWrapper
();
}
@Override
...
...
@@ -40,6 +45,10 @@ public class DecompileTask extends CancelableBackgroundTask {
@Override
public
List
<
Runnable
>
scheduleJobs
()
{
if
(
mainWindow
.
getCacheObject
().
isFullDecompilationFinished
())
{
return
Collections
.
emptyList
();
}
List
<
JavaClass
>
classes
=
wrapper
.
getIncludedClasses
();
expectedCompleteCount
=
classes
.
size
();
complete
.
set
(
0
);
...
...
@@ -87,7 +96,41 @@ public class DecompileTask extends CancelableBackgroundTask {
+
", time limit:{ total: "
+
timeLimit
+
"ms, per cls: "
+
CLS_LIMIT
+
"ms }"
+
", status: "
+
taskInfo
.
getStatus
());
}
this
.
result
=
new
ProcessResult
(
skippedCls
,
taskInfo
.
getStatus
(),
timeLimit
);
result
=
new
ProcessResult
(
skippedCls
,
taskInfo
.
getStatus
(),
timeLimit
);
wrapper
.
unloadClasses
();
processDecompilationResults
();
System
.
gc
();
mainWindow
.
getCacheObject
().
setFullDecompilationFinished
(
skippedCls
==
0
);
}
private
void
processDecompilationResults
()
{
int
skippedCls
=
result
.
getSkipped
();
if
(
skippedCls
==
0
)
{
return
;
}
TaskStatus
status
=
result
.
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
(
mainWindow
,
message
);
break
;
}
case
CANCEL_BY_TIMEOUT:
{
String
reason
=
NLS
.
str
(
"message.taskTimeout"
,
result
.
getTimeLimit
());
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
;
}
}
}
@Override
...
...
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
浏览文件 @
5d6b8272
...
...
@@ -95,7 +95,6 @@ import jadx.gui.device.debugger.BreakpointManager;
import
jadx.gui.jobs.BackgroundExecutor
;
import
jadx.gui.jobs.DecompileTask
;
import
jadx.gui.jobs.ExportTask
;
import
jadx.gui.jobs.ProcessResult
;
import
jadx.gui.jobs.TaskStatus
;
import
jadx.gui.plugins.mappings.MappingExporter
;
import
jadx.gui.plugins.quark.QuarkDialog
;
...
...
@@ -173,6 +172,7 @@ public class MainWindow extends JFrame {
private
static
final
ImageIcon
ICON_QUARK
=
UiUtils
.
openSvgIcon
(
"ui/quark"
);
private
static
final
ImageIcon
ICON_PREF
=
UiUtils
.
openSvgIcon
(
"ui/settings"
);
private
static
final
ImageIcon
ICON_DEOBF
=
UiUtils
.
openSvgIcon
(
"ui/helmChartLock"
);
private
static
final
ImageIcon
ICON_DECOMPILE_ALL
=
UiUtils
.
openSvgIcon
(
"ui/runAll"
);
private
static
final
ImageIcon
ICON_LOG
=
UiUtils
.
openSvgIcon
(
"ui/logVerbose"
);
private
static
final
ImageIcon
ICON_INFO
=
UiUtils
.
openSvgIcon
(
"ui/showInfos"
);
private
static
final
ImageIcon
ICON_DEBUGGER
=
UiUtils
.
openSvgIcon
(
"ui/startDebugger"
);
...
...
@@ -608,54 +608,17 @@ public class MainWindow extends JFrame {
new
Timer
().
schedule
(
new
TimerTask
()
{
@Override
public
void
run
()
{
waitDecompileTask
();
requestFullDecompilation
();
}
},
1000
);
}
}
private
static
final
Object
DECOMPILER_TASK_SYNC
=
new
Object
();
public
void
waitDecompileTask
()
{
synchronized
(
DECOMPILER_TASK_SYNC
)
{
try
{
DecompileTask
decompileTask
=
new
DecompileTask
(
wrapper
);
backgroundExecutor
.
executeAndWait
(
decompileTask
);
backgroundExecutor
.
execute
(
decompileTask
.
getTitle
(),
wrapper:
:
unloadClasses
).
get
();
processDecompilationResults
(
decompileTask
.
getResult
());
System
.
gc
();
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Decompile task execution failed"
,
e
);
}
}
}
private
void
processDecompilationResults
(
ProcessResult
decompile
)
{
int
skippedCls
=
decompile
.
getSkipped
();
if
(
skippedCls
==
0
)
{
public
void
requestFullDecompilation
()
{
if
(
cacheObject
.
isFullDecompilationFinished
())
{
return
;
}
TaskStatus
status
=
decompile
.
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
;
}
}
backgroundExecutor
.
execute
(
new
DecompileTask
(
this
));
}
public
void
cancelBackgroundJobs
()
{
...
...
@@ -1041,6 +1004,10 @@ public class MainWindow extends JFrame {
commentSearchAction
.
putValue
(
Action
.
ACCELERATOR_KEY
,
getKeyStroke
(
KeyEvent
.
VK_SEMICOLON
,
UiUtils
.
ctrlButton
()
|
KeyEvent
.
SHIFT_DOWN_MASK
));
ActionHandler
decompileAllAction
=
new
ActionHandler
(
ev
->
requestFullDecompilation
());
decompileAllAction
.
setNameAndDesc
(
NLS
.
str
(
"menu.decompile_all"
));
decompileAllAction
.
setIcon
(
ICON_DECOMPILE_ALL
);
Action
deobfAction
=
new
AbstractAction
(
NLS
.
str
(
"menu.deobfuscation"
),
ICON_DEOBF
)
{
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
...
...
@@ -1152,6 +1119,7 @@ public class MainWindow extends JFrame {
JMenu
tools
=
new
JMenu
(
NLS
.
str
(
"menu.tools"
));
tools
.
setMnemonic
(
KeyEvent
.
VK_T
);
tools
.
add
(
decompileAllAction
);
tools
.
add
(
deobfMenuItem
);
tools
.
add
(
quarkAction
);
tools
.
add
(
openDeviceAction
);
...
...
@@ -1231,6 +1199,7 @@ public class MainWindow extends JFrame {
exportAction
.
setEnabled
(
loaded
);
saveProjectAsAction
.
setEnabled
(
loaded
);
reload
.
setEnabled
(
loaded
);
decompileAllAction
.
setEnabled
(
loaded
);
deobfAction
.
setEnabled
(
loaded
);
quarkAction
.
setEnabled
(
loaded
);
return
false
;
...
...
jadx-gui/src/main/java/jadx/gui/ui/dialog/UsageDialog.java
浏览文件 @
5d6b8272
...
...
@@ -19,11 +19,14 @@ import jadx.api.JavaClass;
import
jadx.api.JavaMethod
;
import
jadx.api.JavaNode
;
import
jadx.api.utils.CodeUtils
;
import
jadx.core.dex.info.ConstStorage
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.jobs.TaskStatus
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.treemodel.CodeNode
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JField
;
import
jadx.gui.treemodel.JMethod
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.ui.MainWindow
;
...
...
@@ -51,6 +54,7 @@ public class UsageDialog extends CommonSearchDialog {
@Override
protected
void
openInit
()
{
progressStartCommon
();
prepareUsageData
();
mainWindow
.
getBackgroundExecutor
().
execute
(
NLS
.
str
(
"progress.load"
),
this
::
collectUsageData
,
(
status
)
->
{
...
...
@@ -63,26 +67,39 @@ public class UsageDialog extends CommonSearchDialog {
});
}
private
void
prepareUsageData
()
{
if
(
mainWindow
.
getSettings
().
isReplaceConsts
()
&&
node
instanceof
JField
)
{
FieldNode
fld
=
((
JField
)
node
).
getJavaField
().
getFieldNode
();
boolean
constField
=
ConstStorage
.
getFieldConstValue
(
fld
)
!=
null
;
if
(
constField
&&
!
fld
.
getAccessFlags
().
isPrivate
())
{
// run full decompilation to prepare for full code scan
mainWindow
.
requestFullDecompilation
();
}
}
}
private
void
collectUsageData
()
{
usageList
=
new
ArrayList
<>();
Map
<
JavaNode
,
List
<
JavaNode
>>
usageQuery
=
buildUsageQuery
();
usageQuery
.
forEach
(
(
searchNode
,
useNodes
)
->
useNodes
.
stream
()
.
map
(
JavaNode:
:
getTopParentClass
)
.
distinct
()
.
forEach
(
u
->
processUsage
(
searchNode
,
u
)));
buildUsageQuery
().
forEach
(
(
searchNode
,
useNodes
)
->
useNodes
.
stream
()
.
map
(
JavaNode:
:
getTopParentClass
)
.
distinct
()
.
forEach
(
u
->
processUsage
(
searchNode
,
u
)));
}
/**
* Return mapping of 'node to search' to 'use places'
*/
private
Map
<
JavaNode
,
List
<
JavaNode
>>
buildUsageQuery
()
{
Map
<
JavaNode
,
List
<
JavaNode
>>
map
=
new
HashMap
<>();
private
Map
<
JavaNode
,
List
<
?
extends
JavaNode
>>
buildUsageQuery
()
{
Map
<
JavaNode
,
List
<
?
extends
JavaNode
>>
map
=
new
HashMap
<>();
if
(
node
instanceof
JMethod
)
{
JavaMethod
javaMethod
=
((
JMethod
)
node
).
getJavaMethod
();
for
(
JavaMethod
mth
:
getMethodWithOverrides
(
javaMethod
))
{
map
.
put
(
mth
,
mth
.
getUseIn
());
}
}
else
if
(
node
instanceof
JClass
)
{
return
map
;
}
if
(
node
instanceof
JClass
)
{
JavaClass
javaCls
=
((
JClass
)
node
).
getCls
();
map
.
put
(
javaCls
,
javaCls
.
getUseIn
());
// add constructors usage into class usage
...
...
@@ -91,10 +108,19 @@ public class UsageDialog extends CommonSearchDialog {
map
.
put
(
javaMth
,
javaMth
.
getUseIn
());
}
}
}
else
{
JavaNode
javaNode
=
node
.
getJavaNode
();
map
.
put
(
javaNode
,
javaNode
.
getUseIn
());
return
map
;
}
if
(
node
instanceof
JField
&&
mainWindow
.
getSettings
().
isReplaceConsts
())
{
FieldNode
fld
=
((
JField
)
node
).
getJavaField
().
getFieldNode
();
boolean
constField
=
ConstStorage
.
getFieldConstValue
(
fld
)
!=
null
;
if
(
constField
&&
!
fld
.
getAccessFlags
().
isPrivate
())
{
// search all classes to collect usage of replaced constants
map
.
put
(
fld
.
getJavaNode
(),
mainWindow
.
getWrapper
().
getIncludedClasses
());
return
map
;
}
}
JavaNode
javaNode
=
node
.
getJavaNode
();
map
.
put
(
javaNode
,
javaNode
.
getUseIn
());
return
map
;
}
...
...
@@ -108,9 +134,12 @@ public class UsageDialog extends CommonSearchDialog {
private
void
processUsage
(
JavaNode
searchNode
,
JavaClass
topUseClass
)
{
ICodeInfo
codeInfo
=
topUseClass
.
getCodeInfo
();
List
<
Integer
>
usePositions
=
topUseClass
.
getUsePlacesFor
(
codeInfo
,
searchNode
);
if
(
usePositions
.
isEmpty
())
{
return
;
}
String
code
=
codeInfo
.
getCodeStr
();
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 "
))
{
...
...
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
浏览文件 @
5d6b8272
...
...
@@ -18,6 +18,8 @@ public class CacheObject {
private
List
<
List
<
JavaClass
>>
decompileBatches
;
private
volatile
boolean
fullDecompilationFinished
;
public
CacheObject
()
{
reset
();
}
...
...
@@ -27,6 +29,7 @@ public class CacheObject {
jNodeCache
=
new
JNodeCache
();
lastSearchOptions
=
new
HashMap
<>();
decompileBatches
=
null
;
fullDecompilationFinished
=
false
;
}
@Nullable
...
...
@@ -53,4 +56,12 @@ public class CacheObject {
public
void
setDecompileBatches
(
List
<
List
<
JavaClass
>>
decompileBatches
)
{
this
.
decompileBatches
=
decompileBatches
;
}
public
boolean
isFullDecompilationFinished
()
{
return
fullDecompilationFinished
;
}
public
void
setFullDecompilationFinished
(
boolean
fullDecompilationFinished
)
{
this
.
fullDecompilationFinished
=
fullDecompilationFinished
;
}
}
jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=Textsuche
menu.class_search
=
Klassen-Suche
menu.comment_search
=
Kommentar suchen
menu.tools
=
Tools
#menu.decompile_all=Decompile all classes
menu.deobfuscation
=
Deobfuskierung
menu.log
=
Log-Anzeige
menu.help
=
Hilfe
...
...
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=Text search
menu.class_search
=
Class search
menu.comment_search
=
Comment searchF
menu.tools
=
Tools
menu.decompile_all
=
Decompile all classes
menu.deobfuscation
=
Deobfuscation
menu.log
=
Log Viewer
menu.help
=
Help
...
...
jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=Buscar texto
menu.class_search
=
Buscar clase
#menu.comment_search=Comment search
menu.tools
=
Herramientas
#menu.decompile_all=Decompile all classes
menu.deobfuscation
=
Desofuscación
menu.log
=
Visor log
menu.help
=
Ayuda
...
...
jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=텍스트 검색
menu.class_search
=
클래스 검색
menu.comment_search
=
주석 검색
menu.tools
=
도구
#menu.decompile_all=Decompile all classes
menu.deobfuscation
=
난독화 해제
menu.log
=
로그 뷰어
menu.help
=
도움말
...
...
jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=Buscar por texto
menu.class_search
=
Buscar por classe
menu.comment_search
=
Busca por comentário
menu.tools
=
Ferramentas
#menu.decompile_all=Decompile all classes
menu.deobfuscation
=
Desofuscar
menu.log
=
Visualizador de log
menu.help
=
Ajuda
...
...
jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=Поиск строк
menu.class_search
=
Поиск классов
menu.comment_search
=
Поиск комментариев
menu.tools
=
Инструменты
#menu.decompile_all=Decompile all classes
menu.deobfuscation
=
Деобфускация
menu.log
=
Просмотр логов
menu.help
=
Помощь
...
...
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=文本搜索
menu.class_search
=
类名搜索
menu.comment_search
=
注释搜索
menu.tools
=
工具
#menu.decompile_all=Decompile all classes
menu.deobfuscation
=
反混淆
menu.log
=
日志查看器
menu.help
=
帮助
...
...
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
浏览文件 @
5d6b8272
...
...
@@ -14,6 +14,7 @@ menu.text_search=文字搜尋
menu.class_search
=
類別搜尋
menu.comment_search
=
註解搜尋
menu.tools
=
工具
#menu.decompile_all=Decompile all classes
menu.deobfuscation
=
去模糊化
menu.log
=
日誌檢視器
menu.help
=
幫助
...
...
jadx-gui/src/main/resources/icons/ui/runAll.svg
0 → 100644
浏览文件 @
5d6b8272
<!-- Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
viewBox=
"0 0 16 16"
>
<g
fill=
"none"
fill-rule=
"evenodd"
>
<polygon
fill=
"#59A869"
points=
"2 2 10 8 2 14"
/>
<path
fill=
"#59A869"
d=
"M7,11.75 L12,8 L7,4.25 L7,2 L15,8 L7,14 L7,11.75 Z"
/>
</g>
</svg>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录