test/hotspot/jtreg/gc/g1/TestGreyReclaimedHumongousObjects.java
changeset 47216 71c04702a3d5
parent 39414 4adf52148100
child 47756 55714c3d544c
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2015, 2016, 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  */
       
    23 
       
    24 /*
       
    25  * @test TestGreyReclaimedHumongousObjects.java
       
    26  * @bug 8069367
       
    27  * @requires vm.gc.G1
       
    28  * @summary Test handling of marked but unscanned reclaimed humongous objects.
       
    29  * @key gc
       
    30  * @modules jdk.management
       
    31  * @run main/othervm -XX:+UseG1GC -Xss32m -Xmx128m -XX:G1HeapRegionSize=1m
       
    32  *      -XX:+UnlockExperimentalVMOptions
       
    33  *          -XX:+G1EagerReclaimHumongousObjects
       
    34  *          -XX:+G1EagerReclaimHumongousObjectsWithStaleRefs
       
    35  *      TestGreyReclaimedHumongousObjects 1048576 90
       
    36  */
       
    37 
       
    38 // This test spawns a bunch of threads, each of them rapidly
       
    39 // allocating large objects and storing them into a circular buffer
       
    40 // associated with the thread.  The circular buffer results in these
       
    41 // objects becoming dead in fairly short order.
       
    42 //
       
    43 // The situation we're trying to provoke is
       
    44 //
       
    45 // (1) A humongous object H is marked and added to the mark stack.
       
    46 //
       
    47 // (2) An evacuation pause determines H is no longer live, and
       
    48 // reclaims it.  This occurs before concurrent marking has gotten
       
    49 // around to processing the mark stack entry for H.
       
    50 //
       
    51 // (3) Concurrent marking processes the mark stack entry for H.  The
       
    52 // bug is that it would attempt to scan the now dead object.
       
    53 //
       
    54 // Unfortunately, this test is *very* sensitive to configuration.
       
    55 // Among the parameters that affect whether / how often we'll get into
       
    56 // the desired situation within a reasonable amount of time are:
       
    57 //
       
    58 // - THREAD_COUNT: The number of allocating threads.
       
    59 //
       
    60 // - OLD_COUNT: The number of objects each thread keeps.
       
    61 //
       
    62 // - MAX_MEMORY: The maximum heap size.
       
    63 //
       
    64 // - G1HeapRegionSize
       
    65 //
       
    66 // - The size of the objects being allocated.
       
    67 //
       
    68 // The parameter values specified here:
       
    69 //
       
    70 // - THREAD_COUNT = 12
       
    71 // - OLD_COUNT == 4
       
    72 // - MAX_MEMORY == 128m
       
    73 // - G1HeapRegionSize = 1m
       
    74 // - Object size = 1048576 (2 regions after header overhead and roundup)
       
    75 //
       
    76 // seems to work well at provoking the desired state fairly quickly.
       
    77 // Even relatively small perturbations may change that.  The key
       
    78 // factors seem to be keeping the heap mostly full of live objects but
       
    79 // having them become dead fairly quickly.
       
    80 
       
    81 import java.util.Date;
       
    82 import java.util.concurrent.ExecutorService;
       
    83 import java.util.concurrent.Executors;
       
    84 import java.util.concurrent.ThreadFactory;
       
    85 import java.util.concurrent.TimeUnit;
       
    86 import com.sun.management.HotSpotDiagnosticMXBean;
       
    87 import java.lang.management.ManagementFactory;
       
    88 
       
    89 public class TestGreyReclaimedHumongousObjects {
       
    90 
       
    91     static class NamedThreadFactory implements ThreadFactory {
       
    92        private int threadNum = 0;
       
    93 
       
    94        @Override
       
    95        public Thread newThread(Runnable r) {
       
    96          return new Thread(r, THREAD_NAME + (threadNum++));
       
    97        }
       
    98     }
       
    99 
       
   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;
       
   105 
       
   106         public Runner(int obj_size) {
       
   107             this.obj_size = obj_size;
       
   108             old_garbage = new Object[OLD_COUNT];
       
   109         }
       
   110 
       
   111         private void allocate_garbage() {
       
   112             byte[] garbage = new byte[obj_size];
       
   113             old_garbage[Math.abs(++old_index % OLD_COUNT)] = garbage;
       
   114         }
       
   115 
       
   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     }
       
   131 
       
   132     public static void main(String[] args) throws Exception {
       
   133         HotSpotDiagnosticMXBean diagnostic =
       
   134                 ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
       
   135 
       
   136         System.out.println("Max memory= " + MAX_MEMORY + " bytes");
       
   137 
       
   138         int obj_size = 0;
       
   139         long seconds_to_run = 0;
       
   140         if (args.length != 2) {
       
   141             throw new RuntimeException("Object size argument must be supplied");
       
   142         } else {
       
   143             obj_size = Integer.parseInt(args[0]);
       
   144             seconds_to_run = Integer.parseInt(args[1]);
       
   145         }
       
   146         System.out.println("Objects size= " + obj_size + " bytes");
       
   147         System.out.println("Seconds to run=" + seconds_to_run);
       
   148 
       
   149         int region_size =
       
   150             Integer.parseInt(diagnostic.getVMOption("G1HeapRegionSize").getValue());
       
   151         if (obj_size < (region_size / 2)) {
       
   152             throw new RuntimeException("Object size " + obj_size +
       
   153                                        " is not humongous with region size " + region_size);
       
   154         }
       
   155 
       
   156         ExecutorService executor =
       
   157             Executors.newFixedThreadPool(THREAD_COUNT, new NamedThreadFactory());
       
   158         System.out.println("Starting " + THREAD_COUNT + " threads");
       
   159 
       
   160         for (int i = 0; i < THREAD_COUNT; i++) {
       
   161             executor.execute(new Runner(obj_size));
       
   162         }
       
   163 
       
   164         Thread.sleep(seconds_to_run * 1000);
       
   165         executor.shutdownNow();
       
   166 
       
   167         if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
       
   168             System.err.println("Thread pool did not terminate after 10 seconds after shutdown");
       
   169         }
       
   170     }
       
   171 
       
   172     private static final long MAX_MEMORY = Runtime.getRuntime().maxMemory();
       
   173     private static final int OLD_COUNT = 4;
       
   174     private static final int THREAD_COUNT = 12;
       
   175     private static final String THREAD_NAME = "TestGreyRH-";
       
   176 }