lin
2025-07-30 fcd736bf35fd93b563e9bbf594f2aa7b62028cc9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
public class RacyMisbehavingLoader extends DefiningLoader {
    static {
        // For JVM, register as parallel capable.
        // Android treats all class loaders as parallel capable and makes this a no-op.
        registerAsParallelCapable();
    }
 
    private Object lock = new Object();
    private int index = 0;
    private int count;
    private boolean throw_error;
 
    private DefiningLoader[] defining_loaders;
 
    public RacyMisbehavingLoader(ClassLoader parent, int count, boolean throw_error) {
        super(parent);
        this.count = count;
        this.throw_error = throw_error;
        defining_loaders = new DefiningLoader[2];
        for (int i = 0; i != defining_loaders.length; ++i) {
            defining_loaders[i] = new DefiningLoader(parent);
        }
    }
 
    public void reportAfterLoading() {
        synchronized (lock) {
            ++index;
            if (index == 2 * count) {
                lock.notifyAll();
            }
        }
    }
 
    protected Class<?> findClass(String name) throws ClassNotFoundException
    {
        if (name.equals("Test")) {
            throw new Error("Unexpected RacyLoader.findClass(\"" + name + "\")");
        }
        return super.findClass(name);
    }
 
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        if (name.equals("Test")) {
            int my_index = syncWithOtherInstances(count);
            Class<?> result;
            if ((my_index & 1) == 0) {
              // Do not delay loading the correct class.
              result = defining_loaders[my_index & 1].loadClass(name, resolve);
            } else {
              // Delay loading the wrong class.
              syncWithOtherInstances(2 * count);
              if (throw_error) {
                throw new Error("RacyMisbehavingLoader throw_error=true");
              }
              result = defining_loaders[my_index & 1].loadClass("Test3", resolve);
            }
            return result;
        }
        return super.loadClass(name, resolve);
    }
 
    private int syncWithOtherInstances(int limit) {
        int my_index;
        synchronized (lock) {
            my_index = index;
            ++index;
            if (index != limit) {
                do {
                    try {
                        lock.wait();
                    } catch (InterruptedException ie) {
                        throw new Error(ie);
                    }
                } while (index < limit);
            } else {
                lock.notifyAll();
            }
        }
        return my_index;
    }
}