Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
ql04210214
jadx
提交
6e5899c6
J
jadx
项目概览
ql04210214
/
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,发现更多精彩内容 >>
未验证
提交
6e5899c6
编写于
8月 04, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: checks for field init reorder (#1599)
上级
c66ffaa7
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
83 addition
and
29 deletion
+83
-29
jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
+4
-0
jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java
+0
-15
jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java
...rc/main/java/jadx/core/dex/visitors/ExtractFieldInit.java
+25
-13
jadx-core/src/main/java/jadx/core/utils/ListUtils.java
jadx-core/src/main/java/jadx/core/utils/ListUtils.java
+4
-0
jadx-core/src/test/java/jadx/tests/api/compiler/TestCompiler.java
...e/src/test/java/jadx/tests/api/compiler/TestCompiler.java
+1
-1
jadx-core/src/test/java/jadx/tests/integration/others/TestFieldInitNegative.java
.../jadx/tests/integration/others/TestFieldInitNegative.java
+49
-0
未找到文件。
jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
浏览文件 @
6e5899c6
...
...
@@ -57,6 +57,10 @@ public class FieldNode extends NotificationAttrNode implements ICodeNode {
return
accFlags
.
isStatic
();
}
public
boolean
isInstance
()
{
return
!
accFlags
.
isStatic
();
}
public
String
getName
()
{
return
fieldInfo
.
getName
();
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/InsnNode.java
浏览文件 @
6e5899c6
...
...
@@ -264,21 +264,6 @@ public class InsnNode extends LineAttrNode {
}
}
public
boolean
canReorderRecursive
()
{
if
(!
canReorder
())
{
return
false
;
}
for
(
InsnArg
arg
:
this
.
getArguments
())
{
if
(
arg
.
isInsnWrap
())
{
InsnNode
wrapInsn
=
((
InsnWrapArg
)
arg
).
getWrapInsn
();
if
(!
wrapInsn
.
canReorderRecursive
())
{
return
false
;
}
}
}
return
true
;
}
public
boolean
containsWrappedInsn
()
{
for
(
InsnArg
arg
:
this
.
getArguments
())
{
if
(
arg
.
isInsnWrap
())
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ExtractFieldInit.java
浏览文件 @
6e5899c6
...
...
@@ -29,6 +29,7 @@ import jadx.core.dex.nodes.MethodNode;
import
jadx.core.dex.visitors.shrink.CodeShrinkVisitor
;
import
jadx.core.utils.BlockUtils
;
import
jadx.core.utils.InsnRemover
;
import
jadx.core.utils.ListUtils
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.JadxException
;
...
...
@@ -45,20 +46,22 @@ public class ExtractFieldInit extends AbstractVisitor {
for
(
ClassNode
inner
:
cls
.
getInnerClasses
())
{
visit
(
inner
);
}
moveStaticFieldsInit
(
cls
);
moveCommonFieldsInit
(
cls
);
if
(!
cls
.
getFields
().
isEmpty
())
{
moveStaticFieldsInit
(
cls
);
moveCommonFieldsInit
(
cls
);
}
return
false
;
}
private
static
final
class
FieldInitInfo
{
final
FieldNode
fieldNode
;
final
IndexInsnNode
putInsn
;
final
boolean
singlePath
;
final
boolean
canMove
;
public
FieldInitInfo
(
FieldNode
fieldNode
,
IndexInsnNode
putInsn
,
boolean
singlePath
)
{
public
FieldInitInfo
(
FieldNode
fieldNode
,
IndexInsnNode
putInsn
,
boolean
canMove
)
{
this
.
fieldNode
=
fieldNode
;
this
.
putInsn
=
putInsn
;
this
.
singlePath
=
singlePath
;
this
.
canMove
=
canMove
;
}
}
...
...
@@ -80,6 +83,9 @@ public class ExtractFieldInit extends AbstractVisitor {
||
classInitMth
.
getBasicBlocks
()
==
null
)
{
return
;
}
if
(
ListUtils
.
noneMatch
(
cls
.
getFields
(),
FieldNode:
:
isStatic
))
{
return
;
}
while
(
processStaticFields
(
cls
,
classInitMth
))
{
// sometimes instructions moved to field init prevent from vars inline -> inline and try again
CodeShrinkVisitor
.
shrinkMethod
(
classInitMth
);
...
...
@@ -116,15 +122,15 @@ public class ExtractFieldInit extends AbstractVisitor {
}
private
static
void
moveCommonFieldsInit
(
ClassNode
cls
)
{
if
(
ListUtils
.
noneMatch
(
cls
.
getFields
(),
FieldNode:
:
isInstance
))
{
return
;
}
List
<
MethodNode
>
constructors
=
getConstructorsList
(
cls
);
if
(
constructors
.
isEmpty
())
{
return
;
}
List
<
ConstructorInitInfo
>
infoList
=
new
ArrayList
<>(
constructors
.
size
());
for
(
MethodNode
constructorMth
:
constructors
)
{
if
(
constructorMth
.
isNoCode
())
{
return
;
}
List
<
FieldInitInfo
>
inits
=
collectFieldsInit
(
cls
,
constructorMth
,
InsnType
.
IPUT
);
filterFieldsInit
(
inits
);
if
(
inits
.
isEmpty
())
{
...
...
@@ -168,19 +174,25 @@ public class ExtractFieldInit extends AbstractVisitor {
Set
<
BlockNode
>
singlePathBlocks
=
new
HashSet
<>();
BlockUtils
.
visitSinglePath
(
mth
.
getEnterBlock
(),
singlePathBlocks:
:
add
);
boolean
canReorder
=
true
;
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
boolean
fieldInsn
=
false
;
if
(
insn
.
getType
()
==
putType
)
{
IndexInsnNode
putInsn
=
(
IndexInsnNode
)
insn
;
FieldInfo
field
=
(
FieldInfo
)
putInsn
.
getIndex
();
if
(
field
.
getDeclClass
().
equals
(
cls
.
getClassInfo
()))
{
FieldNode
fn
=
cls
.
searchField
(
field
);
if
(
fn
!=
null
)
{
boolean
singlePath
=
singlePathBlocks
.
contains
(
block
);
fieldsInit
.
add
(
new
FieldInitInfo
(
fn
,
putInsn
,
singlePath
));
boolean
canMove
=
canReorder
&&
singlePathBlocks
.
contains
(
block
);
fieldsInit
.
add
(
new
FieldInitInfo
(
fn
,
putInsn
,
canMove
));
fieldInsn
=
true
;
}
}
}
if
(!
fieldInsn
&&
canReorder
&&
!
insn
.
canReorder
())
{
canReorder
=
false
;
}
}
}
return
fieldsInit
;
...
...
@@ -226,14 +238,14 @@ public class ExtractFieldInit extends AbstractVisitor {
}
private
static
boolean
checkInsn
(
FieldInitInfo
initInfo
)
{
if
(!
initInfo
.
singlePath
)
{
if
(!
initInfo
.
canMove
)
{
return
false
;
}
IndexInsnNode
insn
=
initInfo
.
putInsn
;
InsnArg
arg
=
insn
.
getArg
(
0
);
if
(
arg
.
isInsnWrap
())
{
InsnNode
wrapInsn
=
((
InsnWrapArg
)
arg
).
getWrapInsn
();
if
(!
wrapInsn
.
canReorder
Recursive
()
&&
insn
.
contains
(
AType
.
EXC_CATCH
))
{
if
(!
wrapInsn
.
canReorder
()
&&
insn
.
contains
(
AType
.
EXC_CATCH
))
{
return
false
;
}
}
else
{
...
...
@@ -364,7 +376,7 @@ public class ExtractFieldInit extends AbstractVisitor {
AccessInfo
accFlags
=
mth
.
getAccessFlags
();
if
(!
accFlags
.
isStatic
()
&&
accFlags
.
isConstructor
())
{
list
.
add
(
mth
);
if
(
BlockUtils
.
isAllBlocksEmpty
(
mth
.
getBasicBlocks
()))
{
if
(
mth
.
isNoCode
()
||
BlockUtils
.
isAllBlocksEmpty
(
mth
.
getBasicBlocks
()))
{
return
Collections
.
emptyList
();
}
}
...
...
jadx-core/src/main/java/jadx/core/utils/ListUtils.java
浏览文件 @
6e5899c6
...
...
@@ -160,6 +160,10 @@ public class ListUtils {
return
true
;
}
public
static
<
T
>
boolean
noneMatch
(
Collection
<
T
>
list
,
Predicate
<
T
>
test
)
{
return
!
anyMatch
(
list
,
test
);
}
public
static
<
T
>
boolean
anyMatch
(
Collection
<
T
>
list
,
Predicate
<
T
>
test
)
{
if
(
list
==
null
||
list
.
isEmpty
())
{
return
false
;
...
...
jadx-core/src/test/java/jadx/tests/api/compiler/TestCompiler.java
浏览文件 @
6e5899c6
...
...
@@ -113,7 +113,7 @@ public class TestCompiler implements Closeable {
assertNotNull
(
mth
,
"Failed to get method "
+
methodName
+
'('
+
Arrays
.
toString
(
types
)
+
')'
);
return
mth
.
invoke
(
inst
,
args
);
}
catch
(
Throwable
e
)
{
IntegrationTest
.
rethrow
(
"Invoke error
"
,
e
);
IntegrationTest
.
rethrow
(
"Invoke error
for method: "
+
methodName
,
e
);
return
null
;
}
}
...
...
jadx-core/src/test/java/jadx/tests/integration/others/TestFieldInitNegative.java
0 → 100644
浏览文件 @
6e5899c6
package
jadx.tests.integration.others
;
import
org.junit.jupiter.api.Test
;
import
jadx.tests.api.IntegrationTest
;
import
static
jadx
.
tests
.
api
.
utils
.
assertj
.
JadxAssertions
.
assertThat
;
/**
* Negative case for field initialization move (#1599).
* Can't reorder with other instance methods.
*/
public
class
TestFieldInitNegative
extends
IntegrationTest
{
public
static
class
TestCls
{
StringBuilder
sb
;
int
field
;
public
TestCls
()
{
initBuilder
(
new
StringBuilder
(
"sb"
));
this
.
field
=
initField
();
this
.
sb
.
append
(
this
.
field
);
}
private
void
initBuilder
(
StringBuilder
sb
)
{
this
.
sb
=
sb
;
}
private
int
initField
()
{
return
sb
.
length
();
}
public
String
getStr
()
{
return
sb
.
toString
();
}
public
void
check
()
{
assertThat
(
new
TestCls
().
getStr
()).
isEqualTo
(
"sb2"
);
// no NPE
}
}
@Test
public
void
test
()
{
assertThat
(
getClassNode
(
TestCls
.
class
))
.
code
()
.
doesNotContain
(
"int field = initField();"
)
.
containsOne
(
"this.field = initField();"
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录