Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
游着的黑鱼
jadx
提交
69574918
J
jadx
项目概览
游着的黑鱼
/
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 搜索 >>
提交
69574918
编写于
2月 02, 2021
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: allow constructor invoke as lambda
上级
f6783e8f
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
116 addition
and
52 deletion
+116
-52
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+15
-6
jadx-core/src/main/java/jadx/core/dex/instructions/InvokeCustomBuilder.java
.../java/jadx/core/dex/instructions/InvokeCustomBuilder.java
+42
-28
jadx-core/src/main/java/jadx/core/dex/instructions/mods/ConstructorInsn.java
...java/jadx/core/dex/instructions/mods/ConstructorInsn.java
+12
-17
jadx-core/src/main/java/jadx/core/dex/visitors/ConstructorVisitor.java
.../main/java/jadx/core/dex/visitors/ConstructorVisitor.java
+9
-1
jadx-core/src/test/java/jadx/tests/integration/java8/TestLambdaConstructor.java
...a/jadx/tests/integration/java8/TestLambdaConstructor.java
+38
-0
未找到文件。
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
浏览文件 @
69574918
...
...
@@ -792,14 +792,23 @@ public class InsnGen {
}
private
void
makeRefLambda
(
CodeWriter
code
,
InvokeCustomNode
customNode
)
{
In
vokeNode
invokeInsn
=
(
InvokeNode
)
customNode
.
getCallInsn
();
MethodInfo
callMth
=
invokeInsn
.
getCallMth
();
if
(
customNode
.
getHandleType
()
==
MethodHandleType
.
INVOKE_STATIC
)
{
In
snNode
callInsn
=
customNode
.
getCallInsn
();
if
(
callInsn
instanceof
ConstructorInsn
)
{
MethodInfo
callMth
=
((
ConstructorInsn
)
callInsn
).
getCallMth
();
useClass
(
code
,
callMth
.
getDeclClass
());
}
else
{
code
.
add
(
"this"
);
code
.
add
(
"::new"
);
return
;
}
if
(
callInsn
instanceof
InvokeNode
)
{
InvokeNode
invokeInsn
=
(
InvokeNode
)
callInsn
;
MethodInfo
callMth
=
invokeInsn
.
getCallMth
();
if
(
customNode
.
getHandleType
()
==
MethodHandleType
.
INVOKE_STATIC
)
{
useClass
(
code
,
callMth
.
getDeclClass
());
}
else
{
code
.
add
(
"this"
);
}
code
.
add
(
"::"
).
add
(
callMth
.
getAlias
());
}
code
.
add
(
"::"
).
add
(
callMth
.
getAlias
());
}
private
void
makeSimpleLambda
(
CodeWriter
code
,
InvokeCustomNode
customNode
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/InvokeCustomBuilder.java
浏览文件 @
69574918
...
...
@@ -17,6 +17,7 @@ import jadx.core.dex.info.MethodInfo;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.NamedArg
;
import
jadx.core.dex.instructions.mods.ConstructorInsn
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.RootNode
;
...
...
@@ -61,21 +62,56 @@ public class InvokeCustomBuilder {
invokeCustomNode
.
setImplMthInfo
(
implMthInfo
);
MethodInfo
callMthInfo
=
MethodInfo
.
fromRef
(
root
,
callMthHandle
.
getMethodRef
());
InvokeNode
invokeNode
=
buildInvokeNode
(
methodHandleType
,
invokeCustomNode
,
callMthInfo
);
if
(
methodHandleType
==
MethodHandleType
.
INVOKE_CONSTRUCTOR
)
{
ConstructorInsn
ctrInsn
=
new
ConstructorInsn
(
mth
,
invokeNode
);
invokeCustomNode
.
setCallInsn
(
ctrInsn
);
}
else
{
invokeCustomNode
.
setCallInsn
(
invokeNode
);
}
MethodNode
callMth
=
root
.
resolveMethod
(
callMthInfo
);
if
(
callMth
!=
null
)
{
invokeCustomNode
.
getCallInsn
().
addAttr
(
callMth
);
if
(
callMth
.
getAccessFlags
().
isSynthetic
()
&&
callMth
.
getUseIn
().
size
()
<=
1
&&
callMth
.
getParentClass
().
equals
(
mth
.
getParentClass
()))
{
// inline only synthetic methods from same class
callMth
.
add
(
AFlag
.
DONT_GENERATE
);
invokeCustomNode
.
setInlineInsn
(
true
);
}
}
if
(!
invokeCustomNode
.
isInlineInsn
())
{
IMethodProto
effectiveMthProto
=
(
IMethodProto
)
values
.
get
(
5
).
getValue
();
List
<
ArgType
>
args
=
Utils
.
collectionMap
(
effectiveMthProto
.
getArgTypes
(),
ArgType:
:
parse
);
boolean
sameArgs
=
args
.
equals
(
callMthInfo
.
getArgumentsTypes
());
invokeCustomNode
.
setUseRef
(
sameArgs
);
}
// prevent args inlining into not generated invoke custom node
for
(
InsnArg
arg
:
invokeCustomNode
.
getArguments
())
{
arg
.
add
(
AFlag
.
DONT_INLINE
);
}
return
invokeCustomNode
;
}
@NotNull
private
static
InvokeNode
buildInvokeNode
(
MethodHandleType
methodHandleType
,
InvokeCustomNode
invokeCustomNode
,
MethodInfo
callMthInfo
)
{
InvokeType
invokeType
=
convertInvokeType
(
methodHandleType
);
int
callArgsCount
=
callMthInfo
.
getArgsCount
();
boolean
instanceCall
=
invokeType
!=
InvokeType
.
STATIC
;
if
(
instanceCall
)
{
callArgsCount
++;
}
InvokeNode
callInsn
=
new
InvokeNode
(
callMthInfo
,
invokeType
,
callArgsCount
);
invokeCustomNode
.
setCallInsn
(
callInsn
);
InvokeNode
invokeNode
=
new
InvokeNode
(
callMthInfo
,
invokeType
,
callArgsCount
);
// copy insn args
int
argsCount
=
invokeCustomNode
.
getArgsCount
();
for
(
int
i
=
0
;
i
<
argsCount
;
i
++)
{
InsnArg
arg
=
invokeCustomNode
.
getArg
(
i
);
callInsn
.
addArg
(
arg
.
duplicate
());
invokeNode
.
addArg
(
arg
.
duplicate
());
}
if
(
callArgsCount
>
argsCount
)
{
// fill remaining args with NamedArg
...
...
@@ -92,33 +128,10 @@ public class InvokeCustomBuilder {
}
else
{
argType
=
callArgTypes
.
get
(
callArgNum
++);
}
callInsn
.
addArg
(
new
NamedArg
(
"v"
+
i
,
argType
));
}
}
MethodNode
callMth
=
root
.
resolveMethod
(
callMthInfo
);
if
(
callMth
!=
null
)
{
callInsn
.
addAttr
(
callMth
);
if
(
callMth
.
getAccessFlags
().
isSynthetic
()
&&
callMth
.
getUseIn
().
size
()
<=
1
&&
callMth
.
getParentClass
().
equals
(
mth
.
getParentClass
()))
{
// inline only synthetic methods from same class
callMth
.
add
(
AFlag
.
DONT_GENERATE
);
invokeCustomNode
.
setInlineInsn
(
true
);
invokeNode
.
addArg
(
new
NamedArg
(
"v"
+
i
,
argType
));
}
}
if
(!
invokeCustomNode
.
isInlineInsn
())
{
IMethodProto
effectiveMthProto
=
(
IMethodProto
)
values
.
get
(
5
).
getValue
();
List
<
ArgType
>
args
=
Utils
.
collectionMap
(
effectiveMthProto
.
getArgTypes
(),
ArgType:
:
parse
);
boolean
sameArgs
=
args
.
equals
(
callMthInfo
.
getArgumentsTypes
());
invokeCustomNode
.
setUseRef
(
sameArgs
);
}
// prevent args inlining into not generated invoke custom node
for
(
InsnArg
arg
:
invokeCustomNode
.
getArguments
())
{
arg
.
add
(
AFlag
.
DONT_INLINE
);
}
return
invokeCustomNode
;
return
invokeNode
;
}
/**
...
...
@@ -149,6 +162,7 @@ public class InvokeCustomBuilder {
case
INVOKE_INSTANCE:
return
InvokeType
.
VIRTUAL
;
case
INVOKE_DIRECT:
case
INVOKE_CONSTRUCTOR:
return
InvokeType
.
DIRECT
;
case
INVOKE_INTERFACE:
return
InvokeType
.
INTERFACE
;
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/mods/ConstructorInsn.java
浏览文件 @
69574918
...
...
@@ -7,6 +7,7 @@ import jadx.core.dex.info.MethodInfo;
import
jadx.core.dex.instructions.BaseInvokeNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.InvokeNode
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
...
...
@@ -26,31 +27,25 @@ public final class ConstructorInsn extends BaseInvokeNode {
public
ConstructorInsn
(
MethodNode
mth
,
InvokeNode
invoke
)
{
super
(
InsnType
.
CONSTRUCTOR
,
invoke
.
getArgsCount
()
-
1
);
this
.
callMth
=
invoke
.
getCallMth
();
ClassInfo
classType
=
callMth
.
getDeclClass
();
RegisterArg
instanceArg
=
(
RegisterArg
)
invoke
.
getArg
(
0
);
this
.
callType
=
getCallType
(
mth
,
callMth
.
getDeclClass
(),
invoke
.
getArg
(
0
));
int
argsCount
=
invoke
.
getArgsCount
();
for
(
int
i
=
1
;
i
<
argsCount
;
i
++)
{
addArg
(
invoke
.
getArg
(
i
));
}
}
private
CallType
getCallType
(
MethodNode
mth
,
ClassInfo
classType
,
InsnArg
instanceArg
)
{
if
(
instanceArg
.
isThis
())
{
if
(
classType
.
equals
(
mth
.
getParentClass
().
getClassInfo
()))
{
if
(
callMth
.
getShortId
().
equals
(
mth
.
getMethodInfo
().
getShortId
()))
{
// self constructor
callType
=
CallType
.
SELF
;
}
else
{
callType
=
CallType
.
THIS
;
return
CallType
.
SELF
;
}
}
else
{
callType
=
CallType
.
SUPER
;
return
CallType
.
THIS
;
}
}
else
{
callType
=
CallType
.
CONSTRUCTOR
;
setResult
(
instanceArg
);
// convert from 'use' to 'assign'
instanceArg
.
getSVar
().
setAssign
(
instanceArg
);
}
instanceArg
.
getSVar
().
removeUse
(
instanceArg
);
int
argsCount
=
invoke
.
getArgsCount
();
for
(
int
i
=
1
;
i
<
argsCount
;
i
++)
{
addArg
(
invoke
.
getArg
(
i
));
return
CallType
.
SUPER
;
}
return
CallType
.
CONSTRUCTOR
;
}
public
ConstructorInsn
(
MethodInfo
callMth
,
CallType
callType
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ConstructorVisitor.java
浏览文件 @
69574918
...
...
@@ -60,8 +60,16 @@ public class ConstructorVisitor extends AbstractVisitor {
if
(!
callMth
.
isConstructor
())
{
return
;
}
InsnNode
instArgAssignInsn
=
((
RegisterArg
)
inv
.
getArg
(
0
)).
getAssignInsn
();
RegisterArg
instanceArg
=
((
RegisterArg
)
inv
.
getArg
(
0
));
InsnNode
instArgAssignInsn
=
instanceArg
.
getAssignInsn
();
ConstructorInsn
co
=
new
ConstructorInsn
(
mth
,
inv
);
if
(
co
.
isNewInstance
())
{
co
.
setResult
(
instanceArg
);
// convert from 'use' to 'assign'
instanceArg
.
getSVar
().
setAssign
(
instanceArg
);
}
instanceArg
.
getSVar
().
removeUse
(
instanceArg
);
co
.
rebindArgs
();
boolean
remove
=
false
;
if
(
co
.
isSuper
()
&&
(
co
.
getArgsCount
()
==
0
||
parentClass
.
isEnum
()))
{
...
...
jadx-core/src/test/java/jadx/tests/integration/java8/TestLambdaConstructor.java
0 → 100644
浏览文件 @
69574918
package
jadx.tests.integration.java8
;
import
java.util.function.Supplier
;
import
org.junit.jupiter.api.Test
;
import
jadx.tests.api.IntegrationTest
;
import
static
jadx
.
tests
.
api
.
utils
.
assertj
.
JadxAssertions
.
assertThat
;
public
class
TestLambdaConstructor
extends
IntegrationTest
{
public
static
class
TestCls
{
public
Supplier
<
Exception
>
test
()
{
return
RuntimeException:
:
new
;
}
public
void
check
()
throws
Exception
{
assertThat
(
test
().
get
()).
isInstanceOf
(
RuntimeException
.
class
);
}
}
@Test
public
void
test
()
{
assertThat
(
getClassNode
(
TestCls
.
class
))
.
code
()
.
containsOne
(
"return RuntimeException::new;"
);
}
@Test
public
void
testFallback
()
{
setFallback
();
assertThat
(
getClassNode
(
TestCls
.
class
))
.
code
()
.
containsOne
(
"RuntimeException::new"
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录