1 /*
   2  * Copyright (c) 2014, 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  */
  23 
  24 /* @test LimitSharedSizes
  25  * @summary Test handling of limits on shared space size
  26  * @library /testlibrary
  27  * @run main LimitSharedSizes
  28  */
  29 
  30 import com.oracle.java.testlibrary.*;
  31 
  32 public class LimitSharedSizes {
  33     static enum Region {
  34         RO, RW, MD, MC
  35     }
  36 
  37     private static class SharedSizeTestData {
  38         public String optionName;
  39         public String optionValue;
  40         public String expectedErrorMsg;
  41 
  42         public SharedSizeTestData(Region region, String value, String msg) {
  43             optionName = getName(region);
  44             optionValue = value;
  45             expectedErrorMsg = msg;
  46         }
  47 
  48         public SharedSizeTestData(Region region, String msg) {
  49             optionName = getName(region);
  50             optionValue = getValue(region);
  51             expectedErrorMsg = msg;
  52         }
  53 
  54         private String getName(Region region) {
  55             String name;
  56             switch (region) {
  57                 case RO:
  58                     name = "-XX:SharedReadOnlySize";
  59                     break;
  60                 case RW:
  61                     name = "-XX:SharedReadWriteSize";
  62                     break;
  63                 case MD:
  64                     name = "-XX:SharedMiscDataSize";
  65                     break;
  66                 case MC:
  67                     name = "-XX:SharedMiscCodeSize";
  68                     break;
  69                 default:
  70                     name = "Unknown";
  71                     break;
  72             }
  73             return name;
  74         }
  75 
  76         private String getValue(Region region) {
  77             String value;
  78             switch (region) {
  79                 case RO:
  80                     value = Platform.is64bit() ? "9M" : "8M";
  81                     break;
  82                 case RW:
  83                     value = Platform.is64bit() ? "12M" : "7M";
  84                     break;
  85                 case MD:
  86                     value = Platform.is64bit() ? "4M" : "2M";
  87                     break;
  88                 case MC:
  89                     value = "120k";
  90                     break;
  91                 default:
  92                     value = "0M";
  93                     break;
  94             }
  95             return value;
  96         }
  97     }
  98 
  99     private static final SharedSizeTestData[] testTable = {
 100         // Too small of a region size should not cause a vm crash.
 101         // It should result in an error message like the following:
 102         // The shared miscellaneous code space is not large enough
 103         // to preload requested classes. Use -XX:SharedMiscCodeSize=
 104         // to increase the initial size of shared miscellaneous code space.
 105         new SharedSizeTestData(Region.RO, "4M",   "read only"),
 106         new SharedSizeTestData(Region.RW, "4M",   "read write"),
 107         new SharedSizeTestData(Region.MD, "50k",  "miscellaneous data"),
 108         new SharedSizeTestData(Region.MC, "20k",  "miscellaneous code"),
 109 
 110         // these values are larger than default ones, but should
 111         // be acceptable and not cause failure
 112         new SharedSizeTestData(Region.RO, "20M", null),
 113         new SharedSizeTestData(Region.RW, "20M", null),
 114         new SharedSizeTestData(Region.MD, "20M", null),
 115         new SharedSizeTestData(Region.MC, "20M", null),
 116 
 117         // test with sizes which just meet the minimum required sizes
 118         // the following tests also attempt to use the shared archive
 119         new SharedSizeTestData(Region.RO, "UseArchive"),
 120         new SharedSizeTestData(Region.RW, "UseArchive"),
 121         new SharedSizeTestData(Region.MD, "UseArchive"),
 122         new SharedSizeTestData(Region.MC, "UseArchive")
 123     };
 124 
 125     public static void main(String[] args) throws Exception {
 126         int counter = 0;
 127         for (SharedSizeTestData td : testTable) {
 128             String fileName = "LimitSharedSizes" + counter + ".jsa";
 129             counter++;
 130 
 131             String option = td.optionName + "=" + td.optionValue;
 132             System.out.println("testing option <" + option + ">");
 133 
 134             ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
 135                "-XX:+UnlockDiagnosticVMOptions",
 136                "-XX:SharedArchiveFile=./" + fileName,
 137                option,
 138                "-Xshare:dump");
 139 
 140             OutputAnalyzer output = new OutputAnalyzer(pb.start());
 141 
 142             if (td.expectedErrorMsg != null) {
 143                 if (!td.expectedErrorMsg.equals("UseArchive")) {
 144                     output.shouldContain("The shared " + td.expectedErrorMsg
 145                         + " space is not large enough");
 146 
 147                     output.shouldHaveExitValue(2);
 148                 } else {
 149                     output.shouldNotContain("space is not large enough");
 150                     output.shouldHaveExitValue(0);
 151 
 152                     // try to use the archive
 153                     pb = ProcessTools.createJavaProcessBuilder(
 154                        "-XX:+UnlockDiagnosticVMOptions",
 155                        "-XX:SharedArchiveFile=./" + fileName,
 156                        "-XX:+PrintSharedArchiveAndExit",
 157                        "-version");
 158 
 159                     try {
 160                         output = new OutputAnalyzer(pb.start());
 161                         output.shouldContain("archive is valid");
 162                     } catch (RuntimeException e) {
 163                         // if sharing failed due to ASLR or similar reasons,
 164                         // check whether sharing was attempted at all (UseSharedSpaces)
 165                         if ((output.getOutput().contains("Unable to use shared archive") ||
 166                              output.getOutput().contains("Unable to map ReadOnly shared space at required address.") ||
 167                              output.getOutput().contains("Unable to map ReadWrite shared space at required address.") ||
 168                              output.getOutput().contains("Unable to reserve shared space at required address")) &&
 169                              output.getExitValue() == 1) {
 170                              System.out.println("Unable to use shared archive: test not executed; assumed passed");
 171                              return;
 172                         }
 173                     }
 174                     output.shouldHaveExitValue(0);
 175                 }
 176             } else {
 177                 output.shouldNotContain("space is not large enough");
 178                 output.shouldHaveExitValue(0);
 179             }
 180         }
 181     }
 182 }