1 /* 2 * Copyright (c) 2013, 2021, 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 26 * @bug 8024927 27 * @summary Testing address of compressed class pointer space as best as possible. 28 * @requires vm.bits == 64 & !vm.graal.enabled 29 * @library /test/lib 30 * @modules java.base/jdk.internal.misc 31 * java.management 32 * @run driver CompressedClassPointers 33 */ 34 35 import jdk.test.lib.Platform; 36 import jdk.test.lib.process.ProcessTools; 37 import jdk.test.lib.process.OutputAnalyzer; 38 import jtreg.SkippedException; 39 40 public class CompressedClassPointers { 41 42 static final String logging_option = "-Xlog:gc+metaspace=trace,cds=trace"; 43 44 // Returns true if we are to test the narrow klass base; we only do this on 45 // platforms where we can be reasonably shure that we get reproducable placement). 46 static boolean testNarrowKlassBase() { 47 if (Platform.isWindows()) { 48 return false; 49 } 50 return true; 51 52 } 53 54 // CDS off, small heap, ccs size default (1G) 55 // A small heap should allow us to place the ccs within the lower 32G and thus allow zero based encoding. 56 public static void smallHeapTest() throws Exception { 57 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 58 "-XX:+UnlockDiagnosticVMOptions", 59 "-XX:SharedBaseAddress=8g", 60 "-Xmx128m", 61 logging_option, 62 "-Xshare:off", 63 "-XX:+VerifyBeforeGC", "-version"); 64 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 65 if (testNarrowKlassBase()) { 66 output.shouldContain("Narrow klass base: 0x0000000000000000"); 67 } 68 output.shouldHaveExitValue(0); 69 } 70 71 // CDS off, small heap, ccs size explicitely set to 1G 72 // A small heap should allow us to place the ccs within the lower 32G and thus allow zero based encoding. 73 public static void smallHeapTestWith1G() throws Exception { 74 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 75 "-XX:+UnlockDiagnosticVMOptions", 76 "-XX:CompressedClassSpaceSize=1g", 77 "-Xmx128m", 78 logging_option, 79 "-Xshare:off", 80 "-XX:+VerifyBeforeGC", "-version"); 81 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 82 if (testNarrowKlassBase()) { 83 output.shouldContain("Narrow klass base: 0x0000000000000000, Narrow klass shift: 3"); 84 } 85 output.shouldHaveExitValue(0); 86 } 87 88 // CDS off, a very large heap, ccs size left to 1G default. 89 // We expect the ccs to be mapped somewhere far beyond the heap, such that it is not possible 90 // to use zero based encoding. 91 public static void largeHeapTest() throws Exception { 92 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 93 "-XX:+UnlockDiagnosticVMOptions", 94 "-XX:+UnlockExperimentalVMOptions", 95 "-Xmx30g", 96 logging_option, 97 "-Xshare:off", 98 "-XX:+VerifyBeforeGC", "-version"); 99 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 100 if (testNarrowKlassBase() && !Platform.isPPC() && !Platform.isOSX()) { 101 // PPC: in most cases the heap cannot be placed below 32g so there 102 // is room for ccs and narrow klass base will be 0x0. Exception: 103 // Linux 4.1.42 or earlier (see ELF_ET_DYN_BASE in JDK-8244847). 104 // For simplicity we exclude PPC. 105 // OSX: similar. 106 output.shouldNotContain("Narrow klass base: 0x0000000000000000"); 107 output.shouldContain("Narrow klass shift: 0"); 108 } 109 output.shouldHaveExitValue(0); 110 } 111 112 // Settings as in largeHeapTest() except for max heap size. We make max heap 113 // size even larger such that it cannot fit into lower 32G but not too large 114 // for compressed oops. 115 // We expect a zerobased ccs. 116 public static void largeHeapAbove32GTest() throws Exception { 117 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 118 "-XX:+UnlockDiagnosticVMOptions", 119 "-XX:+UnlockExperimentalVMOptions", 120 "-Xmx31g", 121 logging_option, 122 "-Xshare:off", 123 "-XX:+VerifyBeforeGC", "-version"); 124 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 125 if (testNarrowKlassBase()) { 126 if (!(Platform.isAArch64() && Platform.isOSX())) { // see JDK-8262895 127 output.shouldContain("Narrow klass base: 0x0000000000000000"); 128 if (!Platform.isAArch64() && !Platform.isOSX()) { 129 output.shouldContain("Narrow klass shift: 0"); 130 } 131 } 132 } 133 output.shouldHaveExitValue(0); 134 } 135 136 // Using large paged heap, metaspace uses small pages. 137 public static void largePagesForHeapTest() throws Exception { 138 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 139 "-XX:+UnlockDiagnosticVMOptions", 140 "-Xmx128m", 141 "-XX:+UseLargePages", 142 logging_option, 143 "-XX:+VerifyBeforeGC", "-version"); 144 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 145 if (testNarrowKlassBase()) { 146 output.shouldContain("Narrow klass base:"); 147 } 148 output.shouldHaveExitValue(0); 149 } 150 151 public static void heapBaseMinAddressTest() throws Exception { 152 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 153 "-XX:HeapBaseMinAddress=1m", 154 "-Xlog:gc+heap+coops=debug", 155 "-version"); 156 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 157 output.shouldContain("HeapBaseMinAddress must be at least"); 158 output.shouldHaveExitValue(0); 159 } 160 161 public static void sharingTest() throws Exception { 162 // Test small heaps 163 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 164 "-XX:+UnlockDiagnosticVMOptions", 165 "-XX:SharedArchiveFile=./CompressedClassPointers.jsa", 166 "-Xmx128m", 167 "-XX:SharedBaseAddress=8g", 168 "-XX:+VerifyBeforeGC", 169 "-Xshare:dump", 170 "-Xlog:cds,gc+heap+coops=debug"); 171 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 172 if (output.firstMatch("Shared spaces are not supported in this VM") != null) { 173 return; 174 } 175 try { 176 output.shouldContain("Loading classes to share"); 177 output.shouldHaveExitValue(0); 178 179 pb = ProcessTools.createJavaProcessBuilder( 180 "-XX:+UnlockDiagnosticVMOptions", 181 "-XX:SharedArchiveFile=./CompressedClassPointers.jsa", 182 "-Xmx128m", 183 "-XX:SharedBaseAddress=8g", 184 "-Xlog:gc+heap+coops=debug", 185 "-Xshare:on", 186 "-version"); 187 output = new OutputAnalyzer(pb.start()); 188 output.shouldContain("sharing"); 189 output.shouldHaveExitValue(0); 190 191 } catch (RuntimeException e) { 192 output.shouldContain("Unable to use shared archive"); 193 output.shouldHaveExitValue(1); 194 } 195 } 196 197 public static void smallHeapTestNoCoop() throws Exception { 198 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 199 "-XX:-UseCompressedOops", 200 "-XX:+UseCompressedClassPointers", 201 "-XX:+UnlockDiagnosticVMOptions", 202 "-XX:SharedBaseAddress=8g", 203 "-Xmx128m", 204 "-Xlog:gc+metaspace=trace", 205 "-Xshare:off", 206 "-Xlog:cds=trace", 207 "-XX:+VerifyBeforeGC", "-version"); 208 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 209 output.shouldContain("Narrow klass base: 0x0000000000000000"); 210 output.shouldHaveExitValue(0); 211 } 212 213 public static void smallHeapTestWith1GNoCoop() throws Exception { 214 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 215 "-XX:-UseCompressedOops", 216 "-XX:+UseCompressedClassPointers", 217 "-XX:+UnlockDiagnosticVMOptions", 218 "-XX:CompressedClassSpaceSize=1g", 219 "-Xmx128m", 220 "-Xlog:gc+metaspace=trace", 221 "-Xshare:off", 222 "-Xlog:cds=trace", 223 "-XX:+VerifyBeforeGC", "-version"); 224 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 225 output.shouldContain("Narrow klass base: 0x0000000000000000"); 226 if (!Platform.isAArch64() && !Platform.isPPC()) { 227 // Currently relax this test for Aarch64 and ppc. 228 output.shouldContain("Narrow klass shift: 0"); 229 } 230 output.shouldHaveExitValue(0); 231 } 232 233 public static void largeHeapTestNoCoop() throws Exception { 234 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 235 "-XX:-UseCompressedOops", 236 "-XX:+UseCompressedClassPointers", 237 "-XX:+UnlockDiagnosticVMOptions", 238 "-XX:+UnlockExperimentalVMOptions", 239 "-Xmx30g", 240 "-Xlog:gc+metaspace=trace", 241 "-Xshare:off", 242 "-Xlog:cds=trace", 243 "-XX:+VerifyBeforeGC", "-version"); 244 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 245 output.shouldContain("Narrow klass base: 0x0000000000000000"); 246 if (!Platform.isAArch64() && !Platform.isPPC()) { 247 // Currently relax this test for Aarch64 and ppc. 248 output.shouldContain("Narrow klass shift: 0"); 249 } 250 output.shouldHaveExitValue(0); 251 } 252 253 public static void largePagesTestNoCoop() throws Exception { 254 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 255 "-XX:-UseCompressedOops", 256 "-XX:+UseCompressedClassPointers", 257 "-XX:+UnlockDiagnosticVMOptions", 258 "-Xmx128m", 259 "-XX:+UseLargePages", 260 "-Xlog:gc+metaspace=trace", 261 "-XX:+VerifyBeforeGC", "-version"); 262 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 263 output.shouldContain("Narrow klass base:"); 264 output.shouldHaveExitValue(0); 265 } 266 267 public static void heapBaseMinAddressTestNoCoop() throws Exception { 268 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 269 "-XX:-UseCompressedOops", 270 "-XX:+UseCompressedClassPointers", 271 "-XX:HeapBaseMinAddress=1m", 272 "-Xlog:gc+heap+coops=debug", 273 "-version"); 274 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 275 output.shouldContain("HeapBaseMinAddress must be at least"); 276 output.shouldHaveExitValue(0); 277 } 278 279 public static void sharingTestNoCoop() throws Exception { 280 // Test small heaps 281 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 282 "-XX:-UseCompressedOops", 283 "-XX:+UseCompressedClassPointers", 284 "-XX:+UnlockDiagnosticVMOptions", 285 "-XX:SharedArchiveFile=./CompressedClassPointers.jsa", 286 "-Xmx128m", 287 "-XX:SharedBaseAddress=8g", 288 "-XX:+VerifyBeforeGC", 289 "-Xshare:dump", 290 "-Xlog:cds,gc+heap+coops=debug"); 291 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 292 if (output.firstMatch("Shared spaces are not supported in this VM") != null) { 293 return; 294 } 295 try { 296 output.shouldContain("Loading classes to share"); 297 output.shouldHaveExitValue(0); 298 299 pb = ProcessTools.createJavaProcessBuilder( 300 "-XX:-UseCompressedOops", 301 "-XX:+UseCompressedClassPointers", 302 "-XX:+UnlockDiagnosticVMOptions", 303 "-XX:SharedArchiveFile=./CompressedClassPointers.jsa", 304 "-Xmx128m", 305 "-XX:SharedBaseAddress=8g", 306 "-Xlog:gc+heap+coops=debug", 307 "-Xshare:on", 308 "-version"); 309 output = new OutputAnalyzer(pb.start()); 310 output.shouldContain("sharing"); 311 output.shouldHaveExitValue(0); 312 313 } catch (RuntimeException e) { 314 output.shouldContain("Unable to use shared archive"); 315 output.shouldHaveExitValue(1); 316 } 317 } 318 319 public static void main(String[] args) throws Exception { 320 smallHeapTest(); 321 smallHeapTestWith1G(); 322 largeHeapTest(); 323 largeHeapAbove32GTest(); 324 largePagesForHeapTest(); 325 heapBaseMinAddressTest(); 326 sharingTest(); 327 328 if (!Platform.isOSX()) { 329 // Testing compressed class pointers without compressed oops. 330 // This is only possible if the platform supports it. Notably, 331 // on macOS, when compressed oops is disabled and the heap is 332 // given an arbitrary address, that address occasionally collides 333 // with where we would ideally have placed the compressed class 334 // space. Therefore, macOS is omitted for now. 335 smallHeapTestNoCoop(); 336 smallHeapTestWith1GNoCoop(); 337 largeHeapTestNoCoop(); 338 largePagesTestNoCoop(); 339 heapBaseMinAddressTestNoCoop(); 340 sharingTestNoCoop(); 341 } 342 } 343 }