15d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/*
25d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Copyright (C) 2009 The Android Open Source Project
35d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao *
45d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Licensed under the Apache License, Version 2.0 (the "License");
55d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * you may not use this file except in compliance with the License.
65d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * You may obtain a copy of the License at
75d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao *
85d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao *      http://www.apache.org/licenses/LICENSE-2.0
95d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao *
105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Unless required by applicable law or agreed to in writing, software
115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * distributed under the License is distributed on an "AS IS" BASIS,
125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * See the License for the specific language governing permissions and
145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * limitations under the License.
155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */
165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.io.File;
185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.ref.WeakReference;
195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.Method;
205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.InvocationTargetException;
215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaopublic class Main {
235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public static volatile boolean quit = false;
245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public static final boolean DEBUG = false;
255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static final boolean WRITE_HPROF_DATA = false;
275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static final int TEST_TIME = 10;
285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static final String OUTPUT_FILE = "gc-thrash.hprof";
295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public static void main(String[] args) {
315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        // dump heap before
325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        System.out.println("Running (" + TEST_TIME + " seconds) ...");
345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        runTests();
355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Method dumpHprofDataMethod = null;
375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        String dumpFile = null;
385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (WRITE_HPROF_DATA) {
405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            dumpHprofDataMethod = getDumpHprofDataMethod();
415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            if (dumpHprofDataMethod != null) {
425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                dumpFile = getDumpFileName();
435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                System.out.println("Sending output to " + dumpFile);
445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            }
455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        System.gc();
485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        System.runFinalization();
495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        System.gc();
505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (WRITE_HPROF_DATA && dumpHprofDataMethod != null) {
525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            try {
535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                dumpHprofDataMethod.invoke(null, dumpFile);
545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            } catch (IllegalAccessException iae) {
555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                System.err.println(iae);
565d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            } catch (InvocationTargetException ite) {
575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                System.err.println(ite);
585d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            }
595d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
605d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
615d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        System.out.println("Done.");
625d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
635d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
645d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    /**
655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * Finds VMDebug.dumpHprofData() through reflection.  In the reference
665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * implementation this will not be available.
675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     *
685d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * @return the reflection object, or null if the method can't be found
695d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     */
705d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static Method getDumpHprofDataMethod() {
715d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        ClassLoader myLoader = Main.class.getClassLoader();
725d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Class vmdClass;
735d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        try {
745d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            vmdClass = myLoader.loadClass("dalvik.system.VMDebug");
755d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        } catch (ClassNotFoundException cnfe) {
765d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            return null;
775d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
785d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
795d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Method meth;
805d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        try {
815d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            meth = vmdClass.getMethod("dumpHprofData",
825d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                    new Class[] { String.class });
835d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        } catch (NoSuchMethodException nsme) {
845d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            System.err.println("Found VMDebug but not dumpHprofData method");
855d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            return null;
865d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
875d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
885d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        return meth;
895d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
905d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
915d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static String getDumpFileName() {
925d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        File tmpDir = new File("/tmp");
935d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (tmpDir.exists() && tmpDir.isDirectory()) {
945d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            return "/tmp/" + OUTPUT_FILE;
955d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
965d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
975d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        File sdcard = new File("/sdcard");
985d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (sdcard.exists() && sdcard.isDirectory()) {
995d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            return "/sdcard/" + OUTPUT_FILE;
1005d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
1015d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1025d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        return null;
1035d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1045d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1055d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1065d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    /**
1075d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * Run the various tests for a set period.
1085d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     */
1095d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public static void runTests() {
1105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Robin robin = new Robin();
1115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Deep deep = new Deep();
1125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Large large = new Large();
1135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        /* start all threads */
1155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        robin.start();
1165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        deep.start();
1175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        large.start();
1185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        /* let everybody run for 10 seconds */
1205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        sleep(TEST_TIME * 1000);
1215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        quit = true;
1235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        try {
1255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            /* wait for all threads to stop */
1265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            robin.join();
1275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            deep.join();
1285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            large.join();
1295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        } catch (InterruptedException ie) {
1305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            System.err.println("join was interrupted");
1315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
1325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    /**
1355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * Sleeps for the "ms" milliseconds.
1365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     */
1375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public static void sleep(int ms) {
1385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        try {
1395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            Thread.sleep(ms);
1405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        } catch (InterruptedException ie) {
1415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            System.err.println("sleep was interrupted");
1425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
1435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    /**
1465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * Sleeps briefly, allowing other threads some CPU time to get started.
1475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     */
1485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public static void startupDelay() {
1495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        sleep(500);
1505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao}
1525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/**
1555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Allocates useless objects and holds on to several of them.
1565d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao *
1575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Uses a single large array of references, replaced repeatedly in round-robin
1585d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * order.
1595d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */
1605d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoclass Robin extends Thread {
1615d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static final int ARRAY_SIZE = 40960;
1625d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    int sleepCount = 0;
1635d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1645d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public void run() {
1655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Main.startupDelay();
1665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        String strings[] = new String[ARRAY_SIZE];
1685d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        int idx = 0;
1695d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1705d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        while (!Main.quit) {
1715d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            strings[idx] = makeString(idx);
1725d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1735d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            if (idx % (ARRAY_SIZE / 4) == 0) {
1745d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                Main.sleep(400);
1755d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                sleepCount++;
1765d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            }
1775d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1785d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            idx = (idx + 1) % ARRAY_SIZE;
1795d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
1805d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1815d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (Main.DEBUG)
1825d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            System.out.println("Robin: sleepCount=" + sleepCount);
1835d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1845d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1855d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private String makeString(int val) {
186cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier        try {
187cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier            return new String("Robin" + val);
188cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier        } catch (OutOfMemoryError e) {
189cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier            return null;
190cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier        }
1915d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
1925d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao}
1935d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1945d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
1955d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/**
1965d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Allocates useless objects in recursive calls.
1975d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */
1985d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoclass Deep extends Thread {
1995d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static final int MAX_DEPTH = 61;
2005d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2015d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static String strong[] = new String[MAX_DEPTH];
2025d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private static WeakReference weak[] = new WeakReference[MAX_DEPTH];
2035d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2045d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public void run() {
2055d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        int iter = 0;
2065d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        boolean once = false;
2075d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2085d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Main.startupDelay();
2095d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        while (!Main.quit) {
2115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            dive(0, iter);
2125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            once = true;
2135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            iter += MAX_DEPTH;
2145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
2155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (!once) {
2175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            System.err.println("not even once?");
2185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            return;
2195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
2205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2215ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz        checkStringReferences();
2225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        /*
2245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao         * Wipe "strong", do a GC, see if "weak" got collected.
2255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao         */
2265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        for (int i = 0; i < MAX_DEPTH; i++)
2275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            strong[i] = null;
2285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2297befd0e35bbed32b90bc0c8b6d3fa8bd612f5506Mathieu Chartier        Runtime.getRuntime().gc();
2305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        for (int i = 0; i < MAX_DEPTH; i++) {
2325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            if (weak[i].get() != null) {
2335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao                System.err.println("Deep: weak still has " + i);
2345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            }
2355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
2365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (Main.DEBUG)
2385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            System.out.println("Deep: iters=" + iter / MAX_DEPTH);
2395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
2405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
2415ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz
2425ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz    /**
2435ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     * Check the results of the last trip through.  Everything in
2445ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     * "weak" should be matched in "strong", and the two should be
2455ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     * equivalent (object-wise, not just string-equality-wise).
2465ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     *
2475ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     * We do that check in a separate method to avoid retaining these
2485ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     * String references in local DEX registers. In interpreter mode,
2495ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     * they would retain these references until the end of the method
2505ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     * or until they are updated to another value.
2515ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz     */
2525ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz    private static void checkStringReferences() {
2535ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz      for (int i = 0; i < MAX_DEPTH; i++) {
2545ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz          if (strong[i] != weak[i].get()) {
2555ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz              System.err.println("Deep: " + i + " strong=" + strong[i] +
2565ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz                  ", weak=" + weak[i].get());
2575ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz          }
2585ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz      }
2595ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz    }
2605ee9454dfee08a70dec62b0ed0fd4ad274274937Sebastien Hertz
2615d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    /**
2625d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * Recursively dive down, setting one or more local variables.
2635d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     *
2645d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * We pad the stack out with locals, attempting to create a mix of
2655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     * valid and invalid references on the stack.
2665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao     */
2675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private String dive(int depth, int iteration) {
2689dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier        try {
2699dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str0;
2709dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str1;
2719dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str2;
2729dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str3;
2739dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str4;
2749dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str5;
2759dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str6;
2769dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String str7;
2779dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            String funStr = "";
2789dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            switch (iteration % 8) {
2799dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 0:
2809dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str0 = makeString(iteration);
2819dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
2829dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 1:
2839dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str1 = makeString(iteration);
2849dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
2859dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 2:
2869dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str2 = makeString(iteration);
2879dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
2889dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 3:
2899dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str3 = makeString(iteration);
2909dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
2919dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 4:
2929dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str4 = makeString(iteration);
2939dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
2949dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 5:
2959dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str5 = makeString(iteration);
2969dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
2979dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 6:
2989dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str6 = makeString(iteration);
2999dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
3009dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                case 7:
3019dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    funStr = str7 = makeString(iteration);
3029dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                    break;
3039dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            }
3045d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
305ed8b53d679d46891d8d405b0ce4a48c282d872f7Nicolas Geoffray            weak[depth] = new WeakReference(funStr);
30667f65ea9ca0826ff16397694bfb9c4858a958453Nicolas Geoffray            strong[depth] = funStr;
3079dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            if (depth+1 < MAX_DEPTH)
3089dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                dive(depth+1, iteration+1);
3099dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            else
3109dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier                Main.sleep(100);
3119dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            return funStr;
3129dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier        } catch (OutOfMemoryError e) {
3139dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            // Silently ignore OOME since gc stress mode causes them to occur but shouldn't be a
3149dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier            // test failure.
3159dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier        }
3169dc0cedd16027858a8d24be6cfc0af63031c22b5Mathieu Chartier        return "";
3175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
3185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
3195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    private String makeString(int val) {
320cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier        try {
321cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier            return new String("Deep" + val);
322cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier        } catch (OutOfMemoryError e) {
323cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier            return null;
324cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier        }
3255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
3265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao}
3275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
3285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
3295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/**
3305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Allocates large useless objects.
3315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */
3325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoclass Large extends Thread {
3335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public void run() {
3345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        byte[] chunk;
3355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        int count = 0;
3365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        int sleepCount = 0;
3375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
3385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        Main.startupDelay();
3395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
3405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        while (!Main.quit) {
341cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier            try {
342cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier                chunk = new byte[100000];
343cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier                pretendToUse(chunk);
344cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier
345cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier                count++;
346cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier                if ((count % 500) == 0) {
347cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier                    Main.sleep(400);
348cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier                    sleepCount++;
349cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier                }
350cecc2d91236cc0394c60eb09fd114342faa44f15Mathieu Chartier            } catch (OutOfMemoryError e) {
3515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            }
3525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        }
3535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
3545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao        if (Main.DEBUG)
3555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao            System.out.println("Large: sleepCount=" + sleepCount);
3565d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    }
3575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao
3585d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao    public void pretendToUse(byte[] chunk) {}
3595d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao}
360