Skip to content

Commit f4f1c5d

Browse files
authored
Add special handling for zero-length arrays to enhance PTA precision (#140)
1 parent 3f3b802 commit f4f1c5d

File tree

8 files changed

+149
-8
lines changed

8 files changed

+149
-8
lines changed

CHANGELOG.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Changelog
22

3-
## [Unreleased] - 2024-12-31
3+
## [Unreleased] - 2025-02-16
4+
5+
### New Features
6+
- Pointer analysis
7+
- Add special handling for zero-length arrays to enhance PTA precision.
48

59
## [0.5.1] - 2024-12-31
610

src/main/java/pascal/taie/analysis/pta/core/heap/AbstractHeapModel.java

+34
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import pascal.taie.World;
2626
import pascal.taie.config.AnalysisOptions;
2727
import pascal.taie.config.ConfigException;
28+
import pascal.taie.ir.exp.Var;
29+
import pascal.taie.ir.exp.NewArray;
30+
import pascal.taie.ir.exp.NumberLiteral;
2831
import pascal.taie.ir.exp.ReferenceLiteral;
2932
import pascal.taie.ir.exp.StringLiteral;
3033
import pascal.taie.ir.stmt.New;
@@ -92,6 +95,10 @@ public abstract class AbstractHeapModel implements HeapModel {
9295

9396
private final Map<MockObj, MockObj> mockObjs = Maps.newMap();
9497

98+
private final Map<Type, Obj> zeroLengthArrays = Maps.newMap();
99+
100+
private static final Descriptor zeroLengthArrayDesc = () -> "ZeroLengthArray";
101+
95102
/**
96103
* Counter for indexing Objs.
97104
*/
@@ -152,9 +159,23 @@ public Obj getObj(New allocSite) {
152159
if (isMergeExceptionObjects && typeSystem.isSubtype(throwable, type)) {
153160
return getMergedObj(allocSite);
154161
}
162+
if (isZeroLengthArrayAlloc(allocSite)) {
163+
return getZeroLengthArrayObj(type);
164+
}
165+
155166
return doGetObj(allocSite);
156167
}
157168

169+
private boolean isZeroLengthArrayAlloc(New allocSite) {
170+
if (!(allocSite.getRValue() instanceof NewArray newArr)) {
171+
return false;
172+
}
173+
Var length = newArr.getLength();
174+
return length.isConst()
175+
&& length.getConstValue() instanceof NumberLiteral numLit
176+
&& numLit.getNumber().longValue() == 0;
177+
}
178+
158179
/**
159180
* Merges given object given by its type.
160181
*
@@ -174,6 +195,19 @@ protected NewObj getNewObj(New allocSite) {
174195
site -> add(new NewObj(site)));
175196
}
176197

198+
/**
199+
* Get the mock object for a zero-length array.
200+
* Arrays with the same type share one mocked representation
201+
*
202+
* @param type the type of allocated zero-length array (e.g. String[])
203+
* @return mock object for the zero-length array
204+
*/
205+
protected Obj getZeroLengthArrayObj(Type type) {
206+
return zeroLengthArrays.computeIfAbsent(type,
207+
t -> getMockObj(zeroLengthArrayDesc,
208+
"<Merged zero-length " + t + ">", t, false));
209+
}
210+
177211
/**
178212
* The method which controls the heap modeling for normal objects.
179213
*/

src/test/java/pascal/taie/analysis/pta/BasicTestFull.java

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public class BasicTestFull extends BasicTest {
5050
@MultiStringsSource({"NativeModel", "distinguish-string-constants:all"})
5151
@MultiStringsSource({"Annotations", "cs:1-call",
5252
"distinguish-string-constants:all"})
53+
@MultiStringsSource({"ZeroLengthArray", "cs:1-obj-1h"})
5354
void testFull(String mainClass, String... opts) {
5455
Tests.testPTA(DIR, mainClass, opts);
5556
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
Points-to sets of all variables
2+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]:<A: void <init>()>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
3+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]:<A: void <init>()>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
4+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: A getObj(int)>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]
5+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: A getObj(int)>/temp$0 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
6+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: A getObj(int)>/temp$2 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
7+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void <init>()>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]
8+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void <init>()>/temp$0 -> [[]:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
9+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void setObj(int,A)>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]
10+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void setObj(int,A)>/a -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
11+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void setObj(int,A)>/temp$0 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
12+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void setObj(int,A)>/temp$1 -> [[]:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
13+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void setObj(int,A)>/temp$3 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}]
14+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:<Container: void setObj(int,A)>/temp$4 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
15+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: A getObj(int)>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]
16+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: A getObj(int)>/temp$0 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
17+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: A getObj(int)>/temp$2 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
18+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void <init>()>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]
19+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void <init>()>/temp$0 -> [[]:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
20+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void setObj(int,A)>/%this -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]
21+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void setObj(int,A)>/a -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
22+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void setObj(int,A)>/temp$0 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
23+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void setObj(int,A)>/temp$1 -> [[]:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
24+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void setObj(int,A)>/temp$3 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}]
25+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:<Container: void setObj(int,A)>/temp$4 -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
26+
[]:<Container: void <clinit>()>/temp$0 -> [[]:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
27+
[]:<ZeroLengthArray: void main(java.lang.String[])>/args -> [[]:EntryPointObj{alloc=MethodParam{<ZeroLengthArray: void main(java.lang.String[])>/0},type=java.lang.String[] in <ZeroLengthArray: void main(java.lang.String[])>}]
28+
[]:<ZeroLengthArray: void main(java.lang.String[])>/ct1 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]
29+
[]:<ZeroLengthArray: void main(java.lang.String[])>/ct2 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]
30+
[]:<ZeroLengthArray: void main(java.lang.String[])>/o1 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
31+
[]:<ZeroLengthArray: void main(java.lang.String[])>/o2 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
32+
[]:<ZeroLengthArray: void main(java.lang.String[])>/res1 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
33+
[]:<ZeroLengthArray: void main(java.lang.String[])>/res2 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
34+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$0 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
35+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$1 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
36+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$2 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]
37+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$3 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]
38+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$4 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
39+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$5 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
40+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$6 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[20@L12] newarray java.lang.Object[%intconst1]}]
41+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$7 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[25@L13] newarray java.lang.Object[%intconst2]}]
42+
[]:<ZeroLengthArray: void main(java.lang.String[])>/temp$8 -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[28@L14] newarray java.lang.Object[%intconst2]}]
43+
44+
Points-to sets of all static fields
45+
<Container: A[] EMPTY> -> [[]:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
46+
47+
Points-to sets of all instance fields
48+
[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}.data -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
49+
[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}.data -> [[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}, []:ZeroLengthArray{alloc=<Merged zero-length A[]>,type=A[]}]
50+
51+
Points-to sets of all array indexes
52+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[6@L5] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}[*] -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
53+
[NewObj{<ZeroLengthArray: void main(java.lang.String[])>[9@L6] new Container}]:NewObj{<Container: void setObj(int,A)>[6@L30] newarray A[temp$2]}[*] -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
54+
[]:EntryPointObj{alloc=MethodParam{<ZeroLengthArray: void main(java.lang.String[])>/0},type=java.lang.String[] in <ZeroLengthArray: void main(java.lang.String[])>}[*] -> [[]:EntryPointObj{alloc=MethodParam{<ZeroLengthArray: void main(java.lang.String[])>/0}[*],type=java.lang.String in <ZeroLengthArray: void main(java.lang.String[])>}]
55+
[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[20@L12] newarray java.lang.Object[%intconst1]}[*] -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}, []:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
56+
[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[25@L13] newarray java.lang.Object[%intconst2]}[*] -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[0@L3] new A}]
57+
[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[28@L14] newarray java.lang.Object[%intconst2]}[*] -> [[]:NewObj{<ZeroLengthArray: void main(java.lang.String[])>[3@L4] new A}]
58+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
class ZeroLengthArray {
2+
public static void main(String[] args) {
3+
A o1 = new A();
4+
A o2 = new A();
5+
Container ct1 = new Container();
6+
Container ct2 = new Container();
7+
ct1.setObj(0, o1);
8+
ct2.setObj(0, o2);
9+
A res1 = ct1.getObj(0);
10+
A res2 = ct2.getObj(0);
11+
12+
PTAAssert.sizeEquals(1, res1, res2);
13+
PTAAssert.contains(res1, o1);
14+
PTAAssert.contains(res2, o2);
15+
}
16+
}
17+
18+
class Container {
19+
private static final A[] EMPTY = new A[0];
20+
private static final int MAX_SIZE = 4;
21+
private A[] data;
22+
23+
public Container() {
24+
data = EMPTY;
25+
}
26+
27+
public void setObj(int index, A a) {
28+
// assert index >= 0 && index < MAX_SIZE;
29+
if (data == EMPTY) {
30+
data = new A[MAX_SIZE];
31+
}
32+
data[index] = a;
33+
}
34+
35+
public A getObj(int index) {
36+
// assert index >= 0 && index < data.length;
37+
return data[index];
38+
}
39+
40+
}
41+
42+
class A {
43+
}
44+

src/test/resources/pta/reflection/ArgsRefine-pta-expected.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ Points-to sets of all variables
1616
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$0 -> [[]:ConstantObj{java.lang.Class: B.class}]
1717
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$1 -> [[]:ReflectionMetaObj{alloc=<B: void print()>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object)>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object,B)>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object,java.lang.Object)>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object,java.lang.Object,java.lang.Object)>,type=java.lang.reflect.Method}]
1818
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$10 -> [[]:ReflectionMetaObj{alloc=<B: void print()>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object)>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object,B)>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object,java.lang.Object)>,type=java.lang.reflect.Method}, []:ReflectionMetaObj{alloc=<B: void print(java.lang.Object,java.lang.Object,java.lang.Object)>,type=java.lang.reflect.Method}]
19-
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$11 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[34@L20] newarray java.lang.Object[%intconst3]}]
19+
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$11 -> [[]:ZeroLengthArray{alloc=<Merged zero-length java.lang.Object[]>,type=java.lang.Object[]}]
2020
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$13 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[36@L21] newarray java.lang.String[%intconst2]}]
2121
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$2 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[6@L12] new B}]
2222
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$3 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[10@L13] newarray java.lang.Object[%intconst2]}]
2323
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$5 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[17@L14] newarray java.lang.String[%intconst2]}]
2424
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$6 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[23@L16] newarray java.lang.Object[%intconst2]}]
2525
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$8 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[27@L17] newarray java.lang.String[%intconst2]}]
26-
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$9 -> [[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[31@L19] newarray java.lang.Class[%intconst3]}]
26+
[]:<ArgsRefine: void invokePrint(java.lang.Class[])>/temp$9 -> [[]:ZeroLengthArray{alloc=<Merged zero-length java.lang.Class[]>,type=java.lang.Class[]}]
2727
[]:<ArgsRefine: void main(java.lang.String[])>/%stringconst1 -> [[]:ConstantObj{java.lang.String: "java.lang.Object"}]
2828
[]:<ArgsRefine: void main(java.lang.String[])>/args -> [[]:EntryPointObj{alloc=MethodParam{<ArgsRefine: void main(java.lang.String[])>/0},type=java.lang.String[] in <ArgsRefine: void main(java.lang.String[])>}]
2929
[]:<ArgsRefine: void main(java.lang.String[])>/temp$0 -> [[]:NewObj{<ArgsRefine: void main(java.lang.String[])>[1@L6] newarray java.lang.Class[%intconst0]}]
@@ -55,7 +55,7 @@ Points-to sets of all array indexes
5555
[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[17@L14] newarray java.lang.String[%intconst2]}[*] -> [[]:ConstantObj{java.lang.String: "<B: void print(java.lang.Object,java.lang.Object)>"}, []:ConstantObj{java.lang.String: "<java.lang.reflect.Method: java.lang.Object invoke(java.lang.Object,java.lang.Object[])>"}]
5656
[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[23@L16] newarray java.lang.Object[%intconst2]}[*] -> [[]:ConstantObj{java.lang.String: "hello"}]
5757
[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[27@L17] newarray java.lang.String[%intconst2]}[*] -> [[]:ConstantObj{java.lang.String: "<B: void print(java.lang.Object,java.lang.Object)>"}, []:ConstantObj{java.lang.String: "<java.lang.reflect.Method: java.lang.Object invoke(java.lang.Object,java.lang.Object[])>"}]
58-
[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[34@L20] newarray java.lang.Object[%intconst3]}[*] -> []
5958
[]:NewObj{<ArgsRefine: void invokePrint(java.lang.Class[])>[36@L21] newarray java.lang.String[%intconst2]}[*] -> [[]:ConstantObj{java.lang.String: "<B: void print()>"}, []:ConstantObj{java.lang.String: "<java.lang.reflect.Method: java.lang.Object invoke(java.lang.Object,java.lang.Object[])>"}]
6059
[]:NewObj{<ArgsRefine: void main(java.lang.String[])>[1@L6] newarray java.lang.Class[%intconst0]}[*] -> [[]:ConstantObj{java.lang.Class: java.lang.Object.class}]
60+
[]:ZeroLengthArray{alloc=<Merged zero-length java.lang.Object[]>,type=java.lang.Object[]}[*] -> []
6161

0 commit comments

Comments
 (0)