Mon, 06 Nov 2017 16:51:47 +0800
[Code Reorganization] remove trailing whitespace to pass jcheck test
kbarrett@7830 | 1 | /* |
kbarrett@7830 | 2 | * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
kbarrett@7830 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
kbarrett@7830 | 4 | * |
kbarrett@7830 | 5 | * This code is free software; you can redistribute it and/or modify it |
kbarrett@7830 | 6 | * under the terms of the GNU General Public License version 2 only, as |
kbarrett@7830 | 7 | * published by the Free Software Foundation. |
kbarrett@7830 | 8 | * |
kbarrett@7830 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
kbarrett@7830 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
kbarrett@7830 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
kbarrett@7830 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
kbarrett@7830 | 13 | * accompanied this code). |
kbarrett@7830 | 14 | * |
kbarrett@7830 | 15 | * You should have received a copy of the GNU General Public License version |
kbarrett@7830 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
kbarrett@7830 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
kbarrett@7830 | 18 | * |
kbarrett@7830 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
kbarrett@7830 | 20 | * or visit www.oracle.com if you need additional information or have any |
kbarrett@7830 | 21 | * questions. |
kbarrett@7830 | 22 | */ |
kbarrett@7830 | 23 | |
kbarrett@7830 | 24 | /* |
kbarrett@7830 | 25 | * @test TestGreyReclaimedHumongousObjects.java |
kbarrett@7830 | 26 | * @bug 8069367 |
kbarrett@7830 | 27 | * @requires vm.gc == "G1" | vm.gc == "null" |
kbarrett@7830 | 28 | * @summary Test handling of marked but unscanned reclaimed humongous objects. |
kbarrett@7830 | 29 | * @key gc |
kbarrett@7830 | 30 | * @run main/othervm -XX:+UseG1GC -Xss32m -Xmx128m -XX:G1HeapRegionSize=1m |
kbarrett@7830 | 31 | * -XX:+UnlockExperimentalVMOptions |
kbarrett@7830 | 32 | * -XX:+G1EagerReclaimHumongousObjects |
kbarrett@7830 | 33 | * -XX:+G1EagerReclaimHumongousObjectsWithStaleRefs |
kbarrett@7830 | 34 | * TestGreyReclaimedHumongousObjects 1048576 90 |
kbarrett@7830 | 35 | */ |
kbarrett@7830 | 36 | |
kbarrett@7830 | 37 | // This test spawns a bunch of threads, each of them rapidly |
kbarrett@7830 | 38 | // allocating large objects and storing them into a circular buffer |
kbarrett@7830 | 39 | // associated with the thread. The circular buffer results in these |
kbarrett@7830 | 40 | // objects becoming dead in fairly short order. |
kbarrett@7830 | 41 | // |
kbarrett@7830 | 42 | // The situation we're trying to provoke is |
kbarrett@7830 | 43 | // |
kbarrett@7830 | 44 | // (1) A humongous object H is marked and added to the mark stack. |
kbarrett@7830 | 45 | // |
kbarrett@7830 | 46 | // (2) An evacuation pause determines H is no longer live, and |
kbarrett@7830 | 47 | // reclaims it. This occurs before concurrent marking has gotten |
kbarrett@7830 | 48 | // around to processing the mark stack entry for H. |
kbarrett@7830 | 49 | // |
kbarrett@7830 | 50 | // (3) Concurrent marking processes the mark stack entry for H. The |
kbarrett@7830 | 51 | // bug is that it would attempt to scan the now dead object. |
kbarrett@7830 | 52 | // |
kbarrett@7830 | 53 | // Unfortunately, this test is *very* sensitive to configuration. |
kbarrett@7830 | 54 | // Among the parameters that affect whether / how often we'll get into |
kbarrett@7830 | 55 | // the desired situation within a reasonable amount of time are: |
kbarrett@7830 | 56 | // |
kbarrett@7830 | 57 | // - THREAD_COUNT: The number of allocating threads. |
kbarrett@7830 | 58 | // |
kbarrett@7830 | 59 | // - OLD_COUNT: The number of objects each thread keeps. |
kbarrett@7830 | 60 | // |
kbarrett@7830 | 61 | // - MAX_MEMORY: The maximum heap size. |
kbarrett@7830 | 62 | // |
kbarrett@7830 | 63 | // - G1HeapRegionSize |
kbarrett@7830 | 64 | // |
kbarrett@7830 | 65 | // - The size of the objects being allocated. |
kbarrett@7830 | 66 | // |
kbarrett@7830 | 67 | // The parameter values specified here: |
kbarrett@7830 | 68 | // |
kbarrett@7830 | 69 | // - THREAD_COUNT = 12 |
kbarrett@7830 | 70 | // - OLD_COUNT == 4 |
kbarrett@7830 | 71 | // - MAX_MEMORY == 128m |
kbarrett@7830 | 72 | // - G1HeapRegionSize = 1m |
kbarrett@7830 | 73 | // - Object size = 1048576 (2 regions after header overhead and roundup) |
kbarrett@7830 | 74 | // |
kbarrett@7830 | 75 | // seems to work well at provoking the desired state fairly quickly. |
kbarrett@7830 | 76 | // Even relatively small perturbations may change that. The key |
kbarrett@7830 | 77 | // factors seem to be keeping the heap mostly full of live objects but |
kbarrett@7830 | 78 | // having them become dead fairly quickly. |
kbarrett@7830 | 79 | |
kbarrett@7830 | 80 | import java.util.Date; |
kbarrett@7830 | 81 | import java.util.concurrent.ExecutorService; |
kbarrett@7830 | 82 | import java.util.concurrent.Executors; |
kbarrett@7830 | 83 | import java.util.concurrent.ThreadFactory; |
kbarrett@7830 | 84 | import java.util.concurrent.TimeUnit; |
kbarrett@7830 | 85 | import sun.management.ManagementFactoryHelper; |
kbarrett@7830 | 86 | import com.sun.management.HotSpotDiagnosticMXBean; |
kbarrett@7830 | 87 | import com.sun.management.VMOption; |
kbarrett@7830 | 88 | |
kbarrett@7830 | 89 | public class TestGreyReclaimedHumongousObjects { |
kbarrett@7830 | 90 | |
kbarrett@7830 | 91 | static class NamedThreadFactory implements ThreadFactory { |
kbarrett@7830 | 92 | private int threadNum = 0; |
kbarrett@7830 | 93 | |
kbarrett@7830 | 94 | @Override |
kbarrett@7830 | 95 | public Thread newThread(Runnable r) { |
kbarrett@7830 | 96 | return new Thread(r, THREAD_NAME + (threadNum++)); |
kbarrett@7830 | 97 | } |
kbarrett@7830 | 98 | } |
kbarrett@7830 | 99 | |
kbarrett@7830 | 100 | static class Runner extends Thread { |
kbarrett@7830 | 101 | private final Date startDate = new Date(); |
kbarrett@7830 | 102 | private final int obj_size; |
kbarrett@7830 | 103 | private final Object[] old_garbage; |
kbarrett@7830 | 104 | private int old_index = 0; |
kbarrett@7830 | 105 | |
kbarrett@7830 | 106 | public Runner(int obj_size) { |
kbarrett@7830 | 107 | this.obj_size = obj_size; |
kbarrett@7830 | 108 | old_garbage = new Object[OLD_COUNT]; |
kbarrett@7830 | 109 | } |
kbarrett@7830 | 110 | |
kbarrett@7830 | 111 | private void allocate_garbage() { |
kbarrett@7830 | 112 | byte[] garbage = new byte[obj_size]; |
kbarrett@7830 | 113 | old_garbage[Math.abs(++old_index % OLD_COUNT)] = garbage; |
kbarrett@7830 | 114 | } |
kbarrett@7830 | 115 | |
kbarrett@7830 | 116 | @Override |
kbarrett@7830 | 117 | public void run() { |
kbarrett@7830 | 118 | try { |
kbarrett@7830 | 119 | while (!isInterrupted()) { |
kbarrett@7830 | 120 | allocate_garbage(); |
kbarrett@7830 | 121 | Thread.sleep(0); // Yield, to ensure interruptable. |
kbarrett@7830 | 122 | } |
kbarrett@7830 | 123 | } catch (InterruptedException e) { |
kbarrett@7830 | 124 | System.out.println("Aborted after " |
kbarrett@7830 | 125 | + (new Date().getTime() - startDate.getTime()) |
kbarrett@7830 | 126 | + " ms"); |
kbarrett@7830 | 127 | interrupt(); |
kbarrett@7830 | 128 | } |
kbarrett@7830 | 129 | } |
kbarrett@7830 | 130 | } |
kbarrett@7830 | 131 | |
kbarrett@7830 | 132 | public static void main(String[] args) throws Exception { |
kbarrett@7830 | 133 | HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); |
kbarrett@7830 | 134 | |
kbarrett@7830 | 135 | System.out.println("Max memory= " + MAX_MEMORY + " bytes"); |
kbarrett@7830 | 136 | |
kbarrett@7830 | 137 | int obj_size = 0; |
kbarrett@7830 | 138 | long seconds_to_run = 0; |
kbarrett@7830 | 139 | if (args.length != 2) { |
kbarrett@7830 | 140 | throw new RuntimeException("Object size argument must be supplied"); |
kbarrett@7830 | 141 | } else { |
kbarrett@7830 | 142 | obj_size = Integer.parseInt(args[0]); |
kbarrett@7830 | 143 | seconds_to_run = Integer.parseInt(args[1]); |
kbarrett@7830 | 144 | } |
kbarrett@7830 | 145 | System.out.println("Objects size= " + obj_size + " bytes"); |
kbarrett@7830 | 146 | System.out.println("Seconds to run=" + seconds_to_run); |
kbarrett@7830 | 147 | |
kbarrett@7830 | 148 | int region_size = |
kbarrett@7830 | 149 | Integer.parseInt(diagnostic.getVMOption("G1HeapRegionSize").getValue()); |
kbarrett@7830 | 150 | if (obj_size < (region_size / 2)) { |
kbarrett@7830 | 151 | throw new RuntimeException("Object size " + obj_size + |
kbarrett@7830 | 152 | " is not humongous with region size " + region_size); |
kbarrett@7830 | 153 | } |
kbarrett@7830 | 154 | |
kbarrett@7830 | 155 | ExecutorService executor = |
kbarrett@7830 | 156 | Executors.newFixedThreadPool(THREAD_COUNT, new NamedThreadFactory()); |
kbarrett@7830 | 157 | System.out.println("Starting " + THREAD_COUNT + " threads"); |
kbarrett@7830 | 158 | |
kbarrett@7830 | 159 | for (int i = 0; i < THREAD_COUNT; i++) { |
kbarrett@7830 | 160 | executor.execute(new Runner(obj_size)); |
kbarrett@7830 | 161 | } |
kbarrett@7830 | 162 | |
kbarrett@7830 | 163 | Thread.sleep(seconds_to_run * 1000); |
kbarrett@7830 | 164 | executor.shutdownNow(); |
kbarrett@7830 | 165 | |
kbarrett@7830 | 166 | if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { |
kbarrett@7830 | 167 | System.err.println("Thread pool did not terminate after 10 seconds after shutdown"); |
kbarrett@7830 | 168 | } |
kbarrett@7830 | 169 | } |
kbarrett@7830 | 170 | |
kbarrett@7830 | 171 | private static final long MAX_MEMORY = Runtime.getRuntime().maxMemory(); |
kbarrett@7830 | 172 | private static final int OLD_COUNT = 4; |
kbarrett@7830 | 173 | private static final int THREAD_COUNT = 12; |
kbarrett@7830 | 174 | private static final String THREAD_NAME = "TestGreyRH-"; |
kbarrett@7830 | 175 | } |
kbarrett@7830 | 176 |