OSDN Git Service

Add test cases for concurrent gc and System.arraycopy
authorJohannes Carlsson <johannes.carlsson.x@sonyericsson.com>
Thu, 3 Feb 2011 14:12:46 +0000 (15:12 +0100)
committerJohan Redestig <johan.redestig@sonymobile.com>
Tue, 5 Jun 2012 08:55:49 +0000 (10:55 +0200)
When System.arraycopy runs at the same time as a concurrent gc
the phone will sometimes crash since System.arraycopy was implemented
using memmove and memcpy. In current implementation of mememove bytes
are copied one at a time. If for instance only 3 out of 4 bytes
to an object reference were copied when the thread switch to the
gc thread occurred and the gc was scanning the marked objects the
gc read an invalid address. The parameters to dvmWriteBarrierArray
in one case was also corrected (they are currently not used).

The fix itself for this crash is made elsewhere, this commit just
adds test cases to verify that this works.

Change-Id: I0a8cfd43561b3d5de4bba818993bcf8b40413045

tests/096-array-copy-concurrent-gc/expected.txt [new file with mode: 0644]
tests/096-array-copy-concurrent-gc/info.txt [new file with mode: 0644]
tests/096-array-copy-concurrent-gc/src/Main.java [new file with mode: 0644]

diff --git a/tests/096-array-copy-concurrent-gc/expected.txt b/tests/096-array-copy-concurrent-gc/expected.txt
new file mode 100644 (file)
index 0000000..23b9dab
--- /dev/null
@@ -0,0 +1,3 @@
+Initializing...
+Starting the test
+Test OK
diff --git a/tests/096-array-copy-concurrent-gc/info.txt b/tests/096-array-copy-concurrent-gc/info.txt
new file mode 100644 (file)
index 0000000..37dd8be
--- /dev/null
@@ -0,0 +1,2 @@
+This is a test to verify that System.arraycopy works nice together with
+the concurrent gc.
diff --git a/tests/096-array-copy-concurrent-gc/src/Main.java b/tests/096-array-copy-concurrent-gc/src/Main.java
new file mode 100644 (file)
index 0000000..c8e538b
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+/**
+ * Running concurrent gc and doing some System.arraycopy
+ * Several threads is created in order to increase the probability
+ * of thread switches at critical points. Without creating several
+ * threads the test case usually passed even when there were bugs.
+ * Size of array and amount of garbage created is based on experimental
+ * numbers and is a tradeoff between time that the test takes when
+ * it succeeds and the probability that the test discovers a problem.
+ */
+public class Main {
+    public static void main(String args[]) {
+        new ObjectCreatorThread(true).start();
+        new ObjectCreatorThread(false).start();
+        new ObjectCreatorThread(false).start();
+    }
+
+    static class ObjectCreatorThread extends Thread {
+        boolean mDoLog;
+        public ObjectCreatorThread(boolean doLog) {
+            mDoLog = doLog;
+        }
+
+        @Override
+        public void run() {
+            new Main().stressArray(mDoLog);
+        }
+    }
+
+    Object [] array = new Object[10000];
+
+    void stressArray(boolean doLog) {
+        // We want many references in the array
+        // We also want elements close to each other to have large
+        // diff in address so lets skip every 2:nd address so it is null
+        if (doLog) {
+            System.out.println("Initializing...");
+        }
+        for (int i = 0; i < array.length; i+=2) {
+            array[i] = new String("Creating some garbage" + i);
+        }
+
+        if (doLog) {
+            System.out.println("Starting the test");
+        }
+
+        for (int j = 0; j < array.length; j++) {
+            Object obj = array[array.length - 1];
+            System.arraycopy(array, 0, array, 1, array.length - 1);
+            array[0] = obj;
+            new String("Creating some garbage" + Math.random());
+            new String("Creating some garbage" + Math.random());
+            new String("Creating some garbage" + Math.random());
+            new String("Creating some garbage" + Math.random());
+        }
+
+        for (int j = 0; j < array.length; j++) {
+            Object obj = array[0];
+            System.arraycopy(array, 1, array, 0, array.length - 1);
+            array[array.length - 1] = obj;
+            new String("Creating some garbage" + Math.random());
+            new String("Creating some garbage" + Math.random());
+            new String("Creating some garbage" + Math.random());
+            new String("Creating some garbage" + Math.random());
+        }
+
+        if (doLog) {
+            System.out.println("Test OK");
+        }
+    }
+}