Revert "Revert "Make sure that const-class linkage is preserved.""
Fix jdwp getting multiple instances of the same class.
Fix counting "zygote"/"non-zygote" classes in class table.
Fix FindClass() to EnsureResolved() classes added by
a racing thread to the class table.
Test: m test-art-host
Test: art/tools/run-jdwp-tests.sh --mode=host --variant=X64 --debug
Bug: 30627598
This reverts commit ecffc67068a28d55d131553bf915fdb9fafbbc03.
Change-Id: I15807949da4f163c2693fac2fbfc274f17685f8a
diff --git a/test/626-const-class-linking/src/RacyMisbehavingLoader.java b/test/626-const-class-linking/src/RacyMisbehavingLoader.java
new file mode 100644
index 0000000..d09888e
--- /dev/null
+++ b/test/626-const-class-linking/src/RacyMisbehavingLoader.java
@@ -0,0 +1,100 @@
+/*
+ * 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) {
+ try {
+ lock.wait(2000);
+ if (index < limit) {
+ throw new Error("Timed out; my_index=" + my_index + ", index=" + index);
+ }
+ } catch (InterruptedException ie) {
+ throw new Error(ie);
+ }
+ } else {
+ lock.notifyAll();
+ }
+ }
+ return my_index;
+ }
+}