xref: /aosp_15_r20/art/test/1960-obsolete-jit-multithread-native/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import art.Redefinition;
18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
19*795d594fSAndroid Build Coastguard Worker import java.util.Arrays;
20*795d594fSAndroid Build Coastguard Worker import java.util.Base64;
21*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.CountDownLatch;
22*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.Phaser;
23*795d594fSAndroid Build Coastguard Worker import java.util.function.Consumer;
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker public class Main {
26*795d594fSAndroid Build Coastguard Worker   public static final int NUM_THREADS = 10;
27*795d594fSAndroid Build Coastguard Worker   public static final boolean PRINT = false;
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker   // import java.util.function.Consumer;
30*795d594fSAndroid Build Coastguard Worker   //
31*795d594fSAndroid Build Coastguard Worker   // class Transform {
32*795d594fSAndroid Build Coastguard Worker   //   public native void nativeSayHi(Consumer<Consumer<String>> r, Consumer<String> rep);
33*795d594fSAndroid Build Coastguard Worker   //   public void sayHi(Consumer<Consumer<String>> r, Consumer<String> reporter) {
34*795d594fSAndroid Build Coastguard Worker   //     reporter.accept("goodbye - Start method sayHi");
35*795d594fSAndroid Build Coastguard Worker   //     r.accept(reporter);
36*795d594fSAndroid Build Coastguard Worker   //     reporter.accept("goodbye - End method sayHi");
37*795d594fSAndroid Build Coastguard Worker   //   }
38*795d594fSAndroid Build Coastguard Worker   // }
39*795d594fSAndroid Build Coastguard Worker   private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
40*795d594fSAndroid Build Coastguard Worker       "yv66vgAAADUAHAoABgASCAATCwAUABUIABYHABcHABgBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP"
41*795d594fSAndroid Build Coastguard Worker       + "TGluZU51bWJlclRhYmxlAQALbmF0aXZlU2F5SGkBAD0oTGphdmEvdXRpbC9mdW5jdGlvbi9Db25z"
42*795d594fSAndroid Build Coastguard Worker       + "dW1lcjtMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyOylWAQAJU2lnbmF0dXJlAQCEKExqYXZh"
43*795d594fSAndroid Build Coastguard Worker       + "L3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI8TGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjxMamF2"
44*795d594fSAndroid Build Coastguard Worker       + "YS9sYW5nL1N0cmluZzs+Oz47TGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjxMamF2YS9sYW5n"
45*795d594fSAndroid Build Coastguard Worker       + "L1N0cmluZzs+OylWAQAFc2F5SGkBAApTb3VyY2VGaWxlAQAOVHJhbnNmb3JtLmphdmEMAAcACAEA"
46*795d594fSAndroid Build Coastguard Worker       + "HGdvb2RieWUgLSBTdGFydCBtZXRob2Qgc2F5SGkHABkMABoAGwEAGmdvb2RieWUgLSBFbmQgbWV0"
47*795d594fSAndroid Build Coastguard Worker       + "aG9kIHNheUhpAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAEAG2phdmEvdXRpbC9mdW5j"
48*795d594fSAndroid Build Coastguard Worker       + "dGlvbi9Db25zdW1lcgEABmFjY2VwdAEAFShMamF2YS9sYW5nL09iamVjdDspVgAgAAUABgAAAAAA"
49*795d594fSAndroid Build Coastguard Worker       + "AwAAAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAcBAQALAAwAAQANAAAA"
50*795d594fSAndroid Build Coastguard Worker       + "AgAOAAEADwAMAAIACQAAADwAAgADAAAAGCwSArkAAwIAKyy5AAMCACwSBLkAAwIAsQAAAAEACgAA"
51*795d594fSAndroid Build Coastguard Worker       + "ABIABAAAABAACAARAA8AEgAXABMADQAAAAIADgABABAAAAACABE=");
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker   private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
54*795d594fSAndroid Build Coastguard Worker       "ZGV4CjAzNQAztWgsKV3wmz41jXurCJpvXfxhxtK7W8NQBAAAcAAAAHhWNBIAAAAAAAAAAJgDAAAV"
55*795d594fSAndroid Build Coastguard Worker       + "AAAAcAAAAAUAAADEAAAAAwAAANgAAAAAAAAAAAAAAAUAAAD8AAAAAQAAACQBAAAMAwAARAEAAKgB"
56*795d594fSAndroid Build Coastguard Worker       + "AACrAQAAswEAALkBAAC/AQAAzAEAAOsBAAD/AQAAEwIAADICAABRAgAAYQIAAGQCAABoAgAAbQIA"
57*795d594fSAndroid Build Coastguard Worker       + "AHUCAACRAgAArwIAALwCAADDAgAAygIAAAQAAAAFAAAABgAAAAgAAAALAAAACwAAAAQAAAAAAAAA"
58*795d594fSAndroid Build Coastguard Worker       + "DAAAAAQAAACYAQAADQAAAAQAAACgAQAAAAAAAAEAAAAAAAIAEQAAAAAAAgASAAAAAgAAAAEAAAAD"
59*795d594fSAndroid Build Coastguard Worker       + "AAEADgAAAAAAAAAAAAAAAgAAAAAAAAAKAAAAeAMAAFgDAAAAAAAAAQABAAEAAACIAQAABAAAAHAQ"
60*795d594fSAndroid Build Coastguard Worker       + "AwAAAA4ABAADAAIAAACMAQAADgAAABoAEAByIAQAAwByIAQAMgAaAg8AciAEACMADgAHAA4AEAIA"
61*795d594fSAndroid Build Coastguard Worker       + "AA5aPFoAAAAAAQAAAAIAAAACAAAAAwADAAEoAAY8aW5pdD4ABD47KVYABD47PjsAC0xUcmFuc2Zv"
62*795d594fSAndroid Build Coastguard Worker       + "cm07AB1MZGFsdmlrL2Fubm90YXRpb24vU2lnbmF0dXJlOwASTGphdmEvbGFuZy9PYmplY3Q7ABJM"
63*795d594fSAndroid Build Coastguard Worker       + "amF2YS9sYW5nL1N0cmluZzsAHUxqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7AB1MamF2YS91"
64*795d594fSAndroid Build Coastguard Worker       + "dGlsL2Z1bmN0aW9uL0NvbnN1bWVyPAAOVHJhbnNmb3JtLmphdmEAAVYAAlZMAANWTEwABmFjY2Vw"
65*795d594fSAndroid Build Coastguard Worker       + "dAAaZ29vZGJ5ZSAtIEVuZCBtZXRob2Qgc2F5SGkAHGdvb2RieWUgLSBTdGFydCBtZXRob2Qgc2F5"
66*795d594fSAndroid Build Coastguard Worker       + "SGkAC25hdGl2ZVNheUhpAAVzYXlIaQAFdmFsdWUAdn5+RDh7ImNvbXBpbGF0aW9uLW1vZGUiOiJk"
67*795d594fSAndroid Build Coastguard Worker       + "ZWJ1ZyIsIm1pbi1hcGkiOjEsInNoYS0xIjoiNzExMWEzNWJhZTZkNTE4NWRjZmIzMzhkNjEwNzRh"
68*795d594fSAndroid Build Coastguard Worker       + "Y2E4NDI2YzAwNiIsInZlcnNpb24iOiIxLjUuMTQtZGV2In0AAgEBExwIFwAXCRcJFwcXAxcJFwcX"
69*795d594fSAndroid Build Coastguard Worker       + "AgAAAQIAgIAExAIBgQIAAQHcAgAAAAAAAAEAAABCAwAAbAMAAAAAAAACAAAAAAAAAAEAAABwAwAA"
70*795d594fSAndroid Build Coastguard Worker       + "AgAAAHADAAAPAAAAAAAAAAEAAAAAAAAAAQAAABUAAABwAAAAAgAAAAUAAADEAAAAAwAAAAMAAADY"
71*795d594fSAndroid Build Coastguard Worker       + "AAAABQAAAAUAAAD8AAAABgAAAAEAAAAkAQAAASAAAAIAAABEAQAAAyAAAAIAAACIAQAAARAAAAIA"
72*795d594fSAndroid Build Coastguard Worker       + "AACYAQAAAiAAABUAAACoAQAABCAAAAEAAABCAwAAACAAAAEAAABYAwAAAxAAAAIAAABsAwAABiAA"
73*795d594fSAndroid Build Coastguard Worker       + "AAEAAAB4AwAAABAAAAEAAACYAwAA");
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker   // A class that we can use to keep track of the output of this test.
76*795d594fSAndroid Build Coastguard Worker   private static class TestWatcher implements Consumer<String> {
77*795d594fSAndroid Build Coastguard Worker     private StringBuilder sb;
78*795d594fSAndroid Build Coastguard Worker     private String thread;
TestWatcher(String thread)79*795d594fSAndroid Build Coastguard Worker     public TestWatcher(String thread) {
80*795d594fSAndroid Build Coastguard Worker       sb = new StringBuilder();
81*795d594fSAndroid Build Coastguard Worker       this.thread = thread;
82*795d594fSAndroid Build Coastguard Worker     }
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker     @Override
accept(String s)85*795d594fSAndroid Build Coastguard Worker     public void accept(String s) {
86*795d594fSAndroid Build Coastguard Worker       String msg = thread + ": \t" + s;
87*795d594fSAndroid Build Coastguard Worker       maybePrint(msg);
88*795d594fSAndroid Build Coastguard Worker       sb.append(msg);
89*795d594fSAndroid Build Coastguard Worker       sb.append('\n');
90*795d594fSAndroid Build Coastguard Worker     }
91*795d594fSAndroid Build Coastguard Worker 
getOutput()92*795d594fSAndroid Build Coastguard Worker     public String getOutput() {
93*795d594fSAndroid Build Coastguard Worker       return sb.toString();
94*795d594fSAndroid Build Coastguard Worker     }
95*795d594fSAndroid Build Coastguard Worker 
clear()96*795d594fSAndroid Build Coastguard Worker     public void clear() {
97*795d594fSAndroid Build Coastguard Worker       sb = new StringBuilder();
98*795d594fSAndroid Build Coastguard Worker     }
99*795d594fSAndroid Build Coastguard Worker   }
100*795d594fSAndroid Build Coastguard Worker 
main(String[] args)101*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws Exception {
102*795d594fSAndroid Build Coastguard Worker     doTest(new Transform());
103*795d594fSAndroid Build Coastguard Worker   }
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker   private static boolean interpreting = true;
106*795d594fSAndroid Build Coastguard Worker 
doTest(Transform t)107*795d594fSAndroid Build Coastguard Worker   public static void doTest(Transform t) throws Exception {
108*795d594fSAndroid Build Coastguard Worker     TestWatcher[] watchers = new TestWatcher[NUM_THREADS];
109*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < NUM_THREADS; i++) {
110*795d594fSAndroid Build Coastguard Worker       watchers[i] = new TestWatcher("Thread " + i);
111*795d594fSAndroid Build Coastguard Worker     }
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker     // This just prints something out to show we are running the Runnable.
114*795d594fSAndroid Build Coastguard Worker     Consumer<Consumer<String>> say_nothing = (Consumer<String> w) -> {
115*795d594fSAndroid Build Coastguard Worker       w.accept("Not doing anything here");
116*795d594fSAndroid Build Coastguard Worker     };
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker     // Run ensureJitCompiled here since it might get GCd
119*795d594fSAndroid Build Coastguard Worker     ensureJitCompiled(Transform.class, "nativeSayHi");
120*795d594fSAndroid Build Coastguard Worker     final CountDownLatch arrive = new CountDownLatch(NUM_THREADS);
121*795d594fSAndroid Build Coastguard Worker     final CountDownLatch depart = new CountDownLatch(1);
122*795d594fSAndroid Build Coastguard Worker     Consumer<Consumer<String>> request_redefine = (Consumer<String> w) -> {
123*795d594fSAndroid Build Coastguard Worker       try {
124*795d594fSAndroid Build Coastguard Worker         arrive.countDown();
125*795d594fSAndroid Build Coastguard Worker         w.accept("Requesting redefinition");
126*795d594fSAndroid Build Coastguard Worker         depart.await();
127*795d594fSAndroid Build Coastguard Worker       } catch (Exception e) {
128*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException("Failed to do something", e);
129*795d594fSAndroid Build Coastguard Worker       }
130*795d594fSAndroid Build Coastguard Worker     };
131*795d594fSAndroid Build Coastguard Worker     Thread redefinition_thread = new RedefinitionThread(arrive, depart);
132*795d594fSAndroid Build Coastguard Worker     redefinition_thread.start();
133*795d594fSAndroid Build Coastguard Worker     Thread[] threads = new Thread[NUM_THREADS];
134*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < NUM_THREADS; i++) {
135*795d594fSAndroid Build Coastguard Worker       threads[i] = new TestThread(t, watchers[i], say_nothing, request_redefine);
136*795d594fSAndroid Build Coastguard Worker       threads[i].start();
137*795d594fSAndroid Build Coastguard Worker     }
138*795d594fSAndroid Build Coastguard Worker     redefinition_thread.join();
139*795d594fSAndroid Build Coastguard Worker     Arrays.stream(threads).forEach((thr) -> {
140*795d594fSAndroid Build Coastguard Worker       try {
141*795d594fSAndroid Build Coastguard Worker         thr.join();
142*795d594fSAndroid Build Coastguard Worker       } catch (Exception e) {
143*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException("Failed to join: ", e);
144*795d594fSAndroid Build Coastguard Worker       }
145*795d594fSAndroid Build Coastguard Worker     });
146*795d594fSAndroid Build Coastguard Worker     Arrays.stream(watchers).forEach((w) -> { System.out.println(w.getOutput()); });
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   private static class RedefinitionThread extends Thread {
150*795d594fSAndroid Build Coastguard Worker     private CountDownLatch arrivalLatch;
151*795d594fSAndroid Build Coastguard Worker     private CountDownLatch departureLatch;
RedefinitionThread(CountDownLatch arrival, CountDownLatch departure)152*795d594fSAndroid Build Coastguard Worker     public RedefinitionThread(CountDownLatch arrival, CountDownLatch departure) {
153*795d594fSAndroid Build Coastguard Worker       super("Redefine thread!");
154*795d594fSAndroid Build Coastguard Worker       this.arrivalLatch = arrival;
155*795d594fSAndroid Build Coastguard Worker       this.departureLatch = departure;
156*795d594fSAndroid Build Coastguard Worker     }
157*795d594fSAndroid Build Coastguard Worker 
run()158*795d594fSAndroid Build Coastguard Worker     public void run() {
159*795d594fSAndroid Build Coastguard Worker       try {
160*795d594fSAndroid Build Coastguard Worker         this.arrivalLatch.await();
161*795d594fSAndroid Build Coastguard Worker         maybePrint("REDEFINITION THREAD: redefining something!");
162*795d594fSAndroid Build Coastguard Worker         Redefinition.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
163*795d594fSAndroid Build Coastguard Worker         maybePrint("REDEFINITION THREAD: redefined something!");
164*795d594fSAndroid Build Coastguard Worker         this.departureLatch.countDown();
165*795d594fSAndroid Build Coastguard Worker       } catch (Exception e) {
166*795d594fSAndroid Build Coastguard Worker         e.printStackTrace(System.out);
167*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException("Failed to redefine", e);
168*795d594fSAndroid Build Coastguard Worker       }
169*795d594fSAndroid Build Coastguard Worker     }
170*795d594fSAndroid Build Coastguard Worker   }
171*795d594fSAndroid Build Coastguard Worker 
maybePrint(String s)172*795d594fSAndroid Build Coastguard Worker   private static synchronized void maybePrint(String s) {
173*795d594fSAndroid Build Coastguard Worker     if (PRINT) {
174*795d594fSAndroid Build Coastguard Worker       System.out.println(s);
175*795d594fSAndroid Build Coastguard Worker     }
176*795d594fSAndroid Build Coastguard Worker   }
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker   private static class TestThread extends Thread {
179*795d594fSAndroid Build Coastguard Worker     private Transform t;
180*795d594fSAndroid Build Coastguard Worker     private TestWatcher w;
181*795d594fSAndroid Build Coastguard Worker     private Consumer<Consumer<String>> do_nothing;
182*795d594fSAndroid Build Coastguard Worker     private Consumer<Consumer<String>> request_redefinition;
TestThread(Transform t, TestWatcher w, Consumer<Consumer<String>> do_nothing, Consumer<Consumer<String>> request_redefinition)183*795d594fSAndroid Build Coastguard Worker     public TestThread(Transform t,
184*795d594fSAndroid Build Coastguard Worker                       TestWatcher w,
185*795d594fSAndroid Build Coastguard Worker                       Consumer<Consumer<String>> do_nothing,
186*795d594fSAndroid Build Coastguard Worker                       Consumer<Consumer<String>> request_redefinition) {
187*795d594fSAndroid Build Coastguard Worker       super();
188*795d594fSAndroid Build Coastguard Worker       this.t = t;
189*795d594fSAndroid Build Coastguard Worker       this.w = w;
190*795d594fSAndroid Build Coastguard Worker       this.do_nothing = do_nothing;
191*795d594fSAndroid Build Coastguard Worker       this.request_redefinition = request_redefinition;
192*795d594fSAndroid Build Coastguard Worker     }
193*795d594fSAndroid Build Coastguard Worker 
run()194*795d594fSAndroid Build Coastguard Worker     public void run() {
195*795d594fSAndroid Build Coastguard Worker       w.clear();
196*795d594fSAndroid Build Coastguard Worker       t.nativeSayHi(do_nothing, w);
197*795d594fSAndroid Build Coastguard Worker       t.nativeSayHi(request_redefinition, w);
198*795d594fSAndroid Build Coastguard Worker       t.nativeSayHi(do_nothing, w);
199*795d594fSAndroid Build Coastguard Worker     }
200*795d594fSAndroid Build Coastguard Worker   }
201*795d594fSAndroid Build Coastguard Worker 
ensureJitCompiled(Class c, String name)202*795d594fSAndroid Build Coastguard Worker   private static native void ensureJitCompiled(Class c, String name);
203*795d594fSAndroid Build Coastguard Worker }
204