test/gc/g1/TestGreyReclaimedHumongousObjects.java

Mon, 06 Nov 2017 16:51:47 +0800

author
aoqi
date
Mon, 06 Nov 2017 16:51:47 +0800
changeset 7997
6cbff0651f1a
parent 7830
b7c8142a9e0b
permissions
-rw-r--r--

[Code Reorganization] remove trailing whitespace to pass jcheck test

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

mercurial