• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import pkg1.A;
18 import pkg1.C;
19 import pkg1.C2;
20 import pkg1.C2I1;
21 import pkg1.C2I2;
22 import pkg1.CXI1;
23 import pkg1.CXI2;
24 import pkg1.I1;
25 import pkg2.B;
26 import pkg2.D;
27 import pkg2.D2;
28 import pkg2.D2I1;
29 import pkg2.D2I2;
30 import pkg2.DXI1;
31 import pkg2.DXI2;
32 import pkg2.I2;
33 
34 public class Main {
main(String args[])35     public static void main(String args[]) {
36         try {
37             Class.forName("dalvik.system.PathClassLoader");
38         } catch (ClassNotFoundException e) {
39             usingRI = true;
40         }
41 
42         // A single method signature can result in multiple vtable entries
43         // when package-private methods from different packages are involved.
44         // All classes here define the method `void foo()` but classes
45         //     class pkg1.A { ... }
46         //     class pkg2.B extends pkg1.A { ... }
47         //     class pkg1.C extends pkg2.B { ... }
48         //     class pkg2.D extends pkg1.C { ... }
49         // define it as package-private and classes
50         //     class pkg1.C2 extends pkg2.B { ... }
51         //     class pkg2.D2 extends pkg1.C2 { ... }
52         // define it as public, so that we can test different cases of overriding.
53 
54         A a = new A();
55         a.callAFoo();  // pkg1.A.foo
56 
57         B b = new B();
58         b.callAFoo();  // pkg1.A.foo (not overridden by pkg2.B.foo)
59         b.callBFoo();  // pkg2.B.foo
60 
61         C c = new C();
62         c.callAFoo();  // pkg1.C.foo (overriddes pkg1.A.foo)
63         c.callBFoo();  // pkg2.B.foo (not overridden by pkg1.C.foo)
64         c.callCFoo();  // pkg1.C.foo
65 
66         D d = new D();
67         d.callAFoo();  // pkg1.C.foo (not overridden by pkg2.D.foo)
68         d.callBFoo();  // pkg2.D.foo (overrides pkg2.B.foo)
69         d.callCFoo();  // pkg1.C.foo (not overridden by pkg2.D.foo)
70         d.callDFoo();  // pkg2.D.foo
71 
72         C2 c2 = new C2();
73         c2.callAFoo();  // pkg1.C2.foo (overriddes pkg1.A.foo)
74         c2.callBFoo();  // pkg2.B.foo (not overridden by pkg1.C2.foo)
75         c2.callC2Foo();  // pkg1.C2.foo
76 
77         D2 d2 = new D2();
78         d2.callAFoo();  // pkg2.D2.foo (overrides public pkg2.C2.foo which overrides pkg1.A.foo)
79         d2.callBFoo();  // pkg2.D2.foo (overrides package-private pkg2.B.foo in the same package)
80         d2.callC2Foo();  // pkg2.D2.foo (overrides public pkg2.C2.foo)
81         d2.callD2Foo();  // pkg2.D2.foo
82 
83         // Interface methods always target the method in the most-derived class with implementation
84         // even when package-private methods from different packages are involved.
85         //
86         // Test interface calls through the following interfaces:
87         //    interface pkg1.I1 { ... }
88         //    interface pkg2.I2 { ... }
89         // that declare a public `void foo()` for concrete classes
90         //    class pkg1.C2I1 extends pkg1.C2 implements pkg1.I1 {}
91         //    class pkg1.C2I2 extends pkg1.C2 implements pkg2.I2 {}
92         //    class pkg2.D2I1 extends pkg2.D2 implements pkg1.I1 {}
93         //    class pkg2.D2I2 extends pkg2.D2 implements pkg2.I2 {}
94         //    class pkg1.CXI1 extends pkg1.CX implements pkg1.I1 {}
95         //    class pkg1.CXI2 extends pkg1.CX implements pkg2.I2 {}
96         //    class pkg2.DXI1 extends pkg2.DX implements pkg1.I1 {}
97         //    class pkg2.DXI2 extends pkg2.DX implements pkg2.I2 {}
98         // with helper classes `pkg1.C2` and `pkg2.D2` from previous tests and helper class
99         //    class pkg2.BX extends pkg1.A { ... }
100         // defining a public `void foo()` but helper classes
101         //    class pkg1.CX extends pkg2.BX { ... }
102         //    class pkg2.DX extends pkg1.CX { ... }
103         // defining a package-private `void foo()`. This is a compilation error in Java,
104         // so we're using different definitions for `pkg1.I1`, `pkg2.I2` and `pkg2.BX` in
105         // src/ for compiling other classes and in src2/ for their run-time definition.
106 
107         C2I1 c2i1 = new C2I1();
108         I1.callI1Foo(c2i1);  // pkg1.C2.foo
109 
110         C2I2 c2i2 = new C2I2();
111         I2.callI2Foo(c2i2);  // pkg1.C2.foo
112 
113         D2I1 d2i1 = new D2I1();
114         I1.callI1Foo(d2i1);  // pkg1.D2.foo
115 
116         D2I2 d2i2 = new D2I2();
117         I2.callI2Foo(d2i2);  // pkg1.D2.foo
118 
119         try {
120             CXI1 cxi1 = new CXI1();
121             I1.callI1Foo(cxi1);
122         } catch (IllegalAccessError expected) {
123             printOnDalvik("Calling pkg1.I1.foo on pkg1.CXI1");
124             System.out.println("Caught IllegalAccessError");
125         }
126 
127         try {
128             CXI2 cxi2 = new CXI2();
129             I2.callI2Foo(cxi2);
130         } catch (IllegalAccessError expected) {
131             printOnDalvik("Calling pkg2.I2.foo on pkg1.CXI2");
132             System.out.println("Caught IllegalAccessError");
133         }
134 
135         try {
136             DXI1 dxi1 = new DXI1();
137             I1.callI1Foo(dxi1);
138         } catch (IllegalAccessError expected) {
139             printOnDalvik("Calling pkg1.I1.foo on pkg2.DXI1");
140             System.out.println("Caught IllegalAccessError");
141         }
142 
143         try {
144             DXI2 dxi2 = new DXI2();
145             I2.callI2Foo(dxi2);
146         } catch (IllegalAccessError expected) {
147             printOnDalvik("Calling pkg2.I2.foo on pkg2.DXI2");
148             System.out.println("Caught IllegalAccessError");
149         }
150     }
151 
printOnDalvik(String line)152     private static void printOnDalvik(String line) {
153         if (!usingRI) {
154             // FIXME: Delay IAE until calling the method. Bug: 211854716
155             System.out.println(line);
156         }
157     }
158 
159     private static boolean usingRI = false;
160 }
161