Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
colcode
jadx
提交
fcd58ae7
J
jadx
项目概览
colcode
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
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 搜索 >>
未验证
提交
fcd58ae7
编写于
5月 30, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: remap class names for store in disk cache (#1503)
上级
df380dea
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
127 addition
and
66 deletion
+127
-66
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+3
-1
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
+35
-0
jadx-gui/src/main/java/jadx/gui/utils/codecache/disk/DiskCodeCache.java
...ain/java/jadx/gui/utils/codecache/disk/DiskCodeCache.java
+89
-65
未找到文件。
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
浏览文件 @
fcd58ae7
...
...
@@ -379,7 +379,9 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
}
}
ICodeInfo
codeInfo
=
root
.
getProcessClasses
().
generateCode
(
this
);
codeCache
.
add
(
clsRawName
,
codeInfo
);
if
(
codeInfo
!=
ICodeInfo
.
EMPTY
)
{
codeCache
.
add
(
clsRawName
,
codeInfo
);
}
return
codeInfo
;
}
...
...
jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java
浏览文件 @
fcd58ae7
...
...
@@ -103,6 +103,10 @@ public class FileUtils {
}
}
public
static
void
deleteFileIfExists
(
Path
filePath
)
throws
IOException
{
Files
.
deleteIfExists
(
filePath
);
}
public
static
boolean
deleteDir
(
File
dir
)
{
File
[]
content
=
dir
.
listFiles
();
if
(
content
!=
null
)
{
...
...
@@ -222,6 +226,15 @@ public class FileUtils {
}
}
public
static
void
writeFile
(
Path
file
,
String
data
)
throws
IOException
{
FileUtils
.
makeDirsForFile
(
file
);
Files
.
write
(
file
,
data
.
getBytes
(
StandardCharsets
.
UTF_8
));
}
public
static
String
readFile
(
Path
textFile
)
throws
IOException
{
return
new
String
(
Files
.
readAllBytes
(
textFile
),
StandardCharsets
.
UTF_8
);
}
@NotNull
public
static
File
prepareFile
(
File
file
)
{
File
saveFile
=
cutFileName
(
file
);
...
...
@@ -259,6 +272,28 @@ public class FileUtils {
return
new
String
(
hexChars
,
StandardCharsets
.
UTF_8
);
}
/**
* Zero padded hex string for first byte
*/
public
static
String
byteToHex
(
int
value
)
{
int
v
=
value
&
0xFF
;
byte
[]
hexChars
=
new
byte
[]
{
HEX_ARRAY
[
v
>>>
4
],
HEX_ARRAY
[
v
&
0x0F
]
};
return
new
String
(
hexChars
,
StandardCharsets
.
US_ASCII
);
}
/**
* Zero padded hex string for int value
*/
public
static
String
intToHex
(
int
value
)
{
byte
[]
hexChars
=
new
byte
[
8
];
int
v
=
value
;
for
(
int
i
=
7
;
i
>=
0
;
i
--)
{
hexChars
[
i
]
=
HEX_ARRAY
[
v
&
0x0F
];
v
>>>=
4
;
}
return
new
String
(
hexChars
,
StandardCharsets
.
US_ASCII
);
}
public
static
boolean
isZipFile
(
File
file
)
{
try
(
InputStream
is
=
new
FileInputStream
(
file
))
{
byte
[]
headers
=
new
byte
[
4
];
...
...
jadx-gui/src/main/java/jadx/gui/utils/codecache/disk/DiskCodeCache.java
浏览文件 @
fcd58ae7
package
jadx.gui.utils.codecache.disk
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.DataInputStream
;
import
java.io.DataOutputStream
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.FileVisitResult
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.PathMatcher
;
import
java.nio.file.SimpleFileVisitor
;
import
java.nio.file.attribute.BasicFileAttributes
;
import
java.nio.file.Paths
;
import
java.nio.file.attribute.FileTime
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
...
...
@@ -34,30 +34,38 @@ import jadx.core.utils.Utils;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.core.utils.files.FileUtils
;
import
static
java
.
nio
.
file
.
StandardOpenOption
.
CREATE
;
import
static
java
.
nio
.
file
.
StandardOpenOption
.
TRUNCATE_EXISTING
;
import
static
java
.
nio
.
file
.
StandardOpenOption
.
WRITE
;
public
class
DiskCodeCache
implements
ICodeCache
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
DiskCodeCache
.
class
);
private
static
final
int
DATA_FORMAT_VERSION
=
10
;
private
static
final
int
DATA_FORMAT_VERSION
=
11
;
private
static
final
byte
[]
JADX_NAMES_MAP_HEADER
=
"jadxnm"
.
getBytes
(
StandardCharsets
.
US_ASCII
);
private
final
Path
srcDir
;
private
final
Path
metaDir
;
private
final
Path
codeVersionFile
;
private
final
Path
namesMapFile
;
private
final
String
codeVersion
;
private
final
CodeMetadataAdapter
codeMetadataAdapter
;
private
final
ExecutorService
writePool
;
private
final
Map
<
String
,
ICodeInfo
>
writeOps
=
new
ConcurrentHashMap
<>();
private
final
Set
<
String
>
cachedKeys
=
Collections
.
synchronizedSet
(
new
HashSet
<>()
);
private
final
Map
<
String
,
Integer
>
namesMap
=
new
ConcurrentHashMap
<>(
);
public
DiskCodeCache
(
RootNode
root
,
Path
baseDir
)
{
srcDir
=
baseDir
.
resolve
(
"sources"
);
metaDir
=
baseDir
.
resolve
(
"metadata"
);
codeVersionFile
=
baseDir
.
resolve
(
"code-version"
);
namesMapFile
=
baseDir
.
resolve
(
"names-map"
);
JadxArgs
args
=
root
.
getArgs
();
codeVersion
=
buildCodeVersion
(
args
);
writePool
=
Executors
.
newFixedThreadPool
(
args
.
getThreadsCount
());
codeMetadataAdapter
=
new
CodeMetadataAdapter
(
root
);
if
(
checkCodeVersion
())
{
collectCachedItems
();
loadNamesMap
();
}
else
{
reset
();
}
...
...
@@ -68,7 +76,7 @@ public class DiskCodeCache implements ICodeCache {
if
(!
Files
.
exists
(
codeVersionFile
))
{
return
false
;
}
String
currentCodeVer
=
readFileToString
(
codeVersionFile
);
String
currentCodeVer
=
FileUtils
.
readFile
(
codeVersionFile
);
return
currentCodeVer
.
equals
(
codeVersion
);
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"Failed to load code version file"
,
e
);
...
...
@@ -82,39 +90,17 @@ public class DiskCodeCache implements ICodeCache {
LOG
.
info
(
"Resetting disk code cache, base dir: {}"
,
srcDir
.
getParent
().
toAbsolutePath
());
FileUtils
.
deleteDirIfExists
(
srcDir
);
FileUtils
.
deleteDirIfExists
(
metaDir
);
FileUtils
.
deleteFileIfExists
(
namesMapFile
);
FileUtils
.
makeDirs
(
srcDir
);
FileUtils
.
makeDirs
(
metaDir
);
writeFile
(
codeVersionFile
,
codeVersion
);
cachedKeys
.
clear
();
FileUtils
.
writeFile
(
codeVersionFile
,
codeVersion
);
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
info
(
"Reset done in: {}ms"
,
System
.
currentTimeMillis
()
-
start
);
}
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Failed to reset code cache"
,
e
);
}
}
private
void
collectCachedItems
()
{
cachedKeys
.
clear
();
try
{
long
start
=
System
.
currentTimeMillis
();
PathMatcher
matcher
=
metaDir
.
getFileSystem
().
getPathMatcher
(
"glob:**.jadxmd"
);
Files
.
walkFileTree
(
metaDir
,
new
SimpleFileVisitor
<
Path
>()
{
@Override
public
FileVisitResult
visitFile
(
Path
file
,
BasicFileAttributes
attrs
)
{
if
(
matcher
.
matches
(
file
))
{
Path
relPath
=
metaDir
.
relativize
(
file
);
String
filePath
=
relPath
.
toString
();
String
clsName
=
filePath
.
substring
(
0
,
filePath
.
length
()
-
7
).
replace
(
File
.
separatorChar
,
'.'
);
cachedKeys
.
add
(
clsName
);
}
return
FileVisitResult
.
CONTINUE
;
}
});
LOG
.
info
(
"Found {} classes metadata in disk cache in {} ms, dir: {}"
,
cachedKeys
.
size
(),
System
.
currentTimeMillis
()
-
start
,
metaDir
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to collect cached items"
,
e
);
}
finally
{
namesMap
.
clear
();
}
}
...
...
@@ -124,11 +110,11 @@ public class DiskCodeCache implements ICodeCache {
@Override
public
void
add
(
String
clsFullName
,
ICodeInfo
codeInfo
)
{
writeOps
.
put
(
clsFullName
,
codeInfo
);
cachedKeys
.
ad
d
(
clsFullName
);
int
clsId
=
getClsI
d
(
clsFullName
);
writePool
.
execute
(()
->
{
try
{
writeFile
(
getJavaFile
(
clsFullName
),
codeInfo
.
getCodeStr
());
codeMetadataAdapter
.
write
(
getMetadataFile
(
cls
FullName
),
codeInfo
.
getCodeMetadata
());
FileUtils
.
writeFile
(
getJavaFile
(
clsId
),
codeInfo
.
getCodeStr
());
codeMetadataAdapter
.
write
(
getMetadataFile
(
cls
Id
),
codeInfo
.
getCodeMetadata
());
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to write code cache for "
+
clsFullName
,
e
);
remove
(
clsFullName
);
...
...
@@ -148,11 +134,12 @@ public class DiskCodeCache implements ICodeCache {
if
(
wrtCodeInfo
!=
null
)
{
return
wrtCodeInfo
.
getCodeStr
();
}
Path
javaFile
=
getJavaFile
(
clsFullName
);
int
clsId
=
getClsId
(
clsFullName
);
Path
javaFile
=
getJavaFile
(
clsId
);
if
(!
Files
.
exists
(
javaFile
))
{
return
null
;
}
return
readFileToString
(
javaFile
);
return
FileUtils
.
readFile
(
javaFile
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to read class code for {}"
,
clsFullName
,
e
);
return
null
;
...
...
@@ -169,12 +156,13 @@ public class DiskCodeCache implements ICodeCache {
if
(
wrtCodeInfo
!=
null
)
{
return
wrtCodeInfo
;
}
Path
javaFile
=
getJavaFile
(
clsFullName
);
int
clsId
=
getClsId
(
clsFullName
);
Path
javaFile
=
getJavaFile
(
clsId
);
if
(!
Files
.
exists
(
javaFile
))
{
return
ICodeInfo
.
EMPTY
;
}
String
code
=
readFileToString
(
javaFile
);
return
codeMetadataAdapter
.
readAndBuild
(
getMetadataFile
(
cls
FullName
),
code
);
String
code
=
FileUtils
.
readFile
(
javaFile
);
return
codeMetadataAdapter
.
readAndBuild
(
getMetadataFile
(
cls
Id
),
code
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to read code cache for {}"
,
clsFullName
,
e
);
return
ICodeInfo
.
EMPTY
;
...
...
@@ -183,34 +171,23 @@ public class DiskCodeCache implements ICodeCache {
@Override
public
boolean
contains
(
String
clsFullName
)
{
return
cachedKeys
.
contains
(
clsFullName
);
return
namesMap
.
containsKey
(
clsFullName
);
}
@Override
public
void
remove
(
String
clsFullName
)
{
try
{
LOG
.
debug
(
"Removing class info from disk: {}"
,
clsFullName
);
cachedKeys
.
remove
(
clsFullName
);
Files
.
deleteIfExists
(
getJavaFile
(
clsFullName
));
Files
.
deleteIfExists
(
getMetadataFile
(
clsFullName
));
Integer
clsId
=
namesMap
.
remove
(
clsFullName
);
if
(
clsId
!=
null
)
{
Files
.
deleteIfExists
(
getJavaFile
(
clsId
));
Files
.
deleteIfExists
(
getMetadataFile
(
clsId
));
}
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Failed to remove code cache for "
+
clsFullName
,
e
);
}
}
private
static
String
readFileToString
(
Path
textFile
)
throws
IOException
{
return
new
String
(
Files
.
readAllBytes
(
textFile
),
StandardCharsets
.
UTF_8
);
}
private
void
writeFile
(
Path
file
,
String
data
)
{
try
{
FileUtils
.
makeDirsForFile
(
file
);
Files
.
write
(
file
,
data
.
getBytes
(
StandardCharsets
.
UTF_8
));
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to write file: {}"
,
file
.
toAbsolutePath
(),
e
);
}
}
private
String
buildCodeVersion
(
JadxArgs
args
)
{
return
DATA_FORMAT_VERSION
+
":"
+
args
.
makeCodeArgsHash
()
...
...
@@ -238,18 +215,65 @@ public class DiskCodeCache implements ICodeCache {
}
}
private
Path
getJavaFile
(
String
clsFullName
)
{
return
srcDir
.
resolve
(
clsFullName
.
replace
(
'.'
,
File
.
separatorChar
)
+
".java"
);
private
int
getClsId
(
String
clsFullName
)
{
return
namesMap
.
computeIfAbsent
(
clsFullName
,
n
->
namesMap
.
size
());
}
private
void
saveNamesMap
()
{
LOG
.
debug
(
"Saving names map for disk cache..."
);
try
(
OutputStream
fileOutput
=
Files
.
newOutputStream
(
namesMapFile
,
WRITE
,
CREATE
,
TRUNCATE_EXISTING
);
DataOutputStream
out
=
new
DataOutputStream
(
new
BufferedOutputStream
(
fileOutput
)))
{
out
.
write
(
JADX_NAMES_MAP_HEADER
);
out
.
writeInt
(
namesMap
.
size
());
for
(
Map
.
Entry
<
String
,
Integer
>
entry
:
namesMap
.
entrySet
())
{
out
.
writeUTF
(
entry
.
getKey
());
out
.
writeInt
(
entry
.
getValue
());
}
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Failed to save names map file"
,
e
);
}
}
private
void
loadNamesMap
()
{
if
(!
Files
.
exists
(
namesMapFile
))
{
reset
();
return
;
}
namesMap
.
clear
();
try
(
InputStream
fileInput
=
Files
.
newInputStream
(
namesMapFile
);
DataInputStream
in
=
new
DataInputStream
(
new
BufferedInputStream
(
fileInput
)))
{
in
.
skipBytes
(
JADX_NAMES_MAP_HEADER
.
length
);
int
count
=
in
.
readInt
();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
String
clsName
=
in
.
readUTF
();
int
clsId
=
in
.
readInt
();
namesMap
.
put
(
clsName
,
clsId
);
}
LOG
.
info
(
"Found {} classes in disk cache, dir: {}"
,
count
,
metaDir
.
getParent
());
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Failed to load names map file"
,
e
);
}
}
private
Path
getJavaFile
(
int
clsId
)
{
return
srcDir
.
resolve
(
getPathForClsId
(
clsId
,
".java"
));
}
private
Path
getMetadataFile
(
int
clsId
)
{
return
metaDir
.
resolve
(
getPathForClsId
(
clsId
,
".jadxmd"
));
}
private
Path
getMetadataFile
(
String
clsFullName
)
{
return
metaDir
.
resolve
(
clsFullName
.
replace
(
'.'
,
File
.
separatorChar
)
+
".jadxmd"
);
private
Path
getPathForClsId
(
int
clsId
,
String
ext
)
{
// all classes divided between 256 top level folders
String
firstByte
=
FileUtils
.
byteToHex
(
clsId
);
return
Paths
.
get
(
firstByte
,
FileUtils
.
intToHex
(
clsId
)
+
ext
);
}
@SuppressWarnings
(
"ResultOfMethodCallIgnored"
)
@Override
public
void
close
()
throws
IOException
{
try
{
saveNamesMap
();
writePool
.
shutdown
();
writePool
.
awaitTermination
(
2
,
TimeUnit
.
MINUTES
);
}
catch
(
InterruptedException
e
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录