1 /*
  2  * Copyright (c) 2014, 2025, 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 8059510
 27  * @summary Test SharedSymbolTableBucketSize option
 28  * @requires vm.cds
 29  * @library /test/lib
 30  * @modules java.base/jdk.internal.misc
 31  *          java.management
 32  */
 33 
 34 import java.util.regex.Matcher;
 35 import java.util.regex.Pattern;
 36 import jdk.test.lib.cds.CDSTestUtils;
 37 import jdk.test.lib.process.OutputAnalyzer;
 38 
 39 public class SharedSymbolTableBucketSize {
 40     public static void main(String[] args) throws Exception {
 41         int bucket_size = 8;
 42 
 43         OutputAnalyzer output =
 44             CDSTestUtils.createArchiveAndCheck("-XX:SharedSymbolTableBucketSize="
 45                                                + Integer.valueOf(bucket_size));
 46         CDSTestUtils.checkMappingFailure(output);
 47 
 48         /* [1] There may be other table stats that precede the symbol tabble.
 49                Skip all thse until we find this:
 50 
 51            [0.677s][info][aot,hashtables] Shared symbol table stats -------- base: 0x0000000800000000
 52            [0.677s][info][aot,hashtables] Number of entries       :     46244
 53            [0.677s][info][aot,hashtables] Total bytes used        :    393792
 54            [0.677s][info][aot,hashtables] Average bytes per entry :     8.516
 55            [0.677s][info][aot,hashtables] Average bucket size     :     7.734
 56            [0.677s][info][aot,hashtables] Variance of bucket size :     7.513
 57            [0.677s][info][aot,hashtables] Std. dev. of bucket size:     2.741
 58            [0.677s][info][aot,hashtables] Maximum bucket size     :        20
 59            [0.677s][info][aot,hashtables] Empty buckets           :         2
 60            [0.677s][info][aot,hashtables] Value_Only buckets      :        24
 61            [0.677s][info][aot,hashtables] Other buckets           :      5953
 62            ....
 63         */
 64         Pattern pattern0 = Pattern.compile("Shared symbol table stats.*", Pattern.DOTALL);
 65         Matcher matcher0 = pattern0.matcher(output.getStdout());
 66         String stat = null;
 67         if (matcher0.find()) {
 68             stat = matcher0.group(0);
 69         }
 70         if (stat == null) {
 71             throw new Exception("FAILED: pattern \"" + pattern0 + "\" not found");
 72         }
 73 
 74         /* (2) The first "Average bucket size" line in the remaining output is for the
 75                shared symbol table */
 76         Pattern pattern = Pattern.compile("Average bucket size *: *([0-9]+\\.[0-9]+).*", Pattern.MULTILINE);
 77         Matcher matcher = pattern.matcher(stat);
 78         String s = null;
 79         if (matcher.find()) {
 80             s = matcher.group(1);
 81         }
 82         if (s == null) {
 83             throw new Exception("FAILED: pattern \"" + pattern + "\" not found");
 84         }
 85 
 86         Float f = Float.parseFloat(s);
 87         int size = Math.round(f);
 88         if (size != bucket_size && size != bucket_size + 1) {
 89             throw new Exception("FAILED: incorrect bucket size " + size +
 90                                 ", expect " + bucket_size + ", or " + (bucket_size + 1));
 91         }
 92 
 93         // Invalid SharedSymbolTableBucketSize input
 94         String input[] = {"-XX:SharedSymbolTableBucketSize=-1",
 95                           "-XX:SharedSymbolTableBucketSize=2.5"};
 96         for (int i = 0; i < input.length; i++) {
 97             CDSTestUtils.createArchive(input[i])
 98                 .shouldContain("Improperly specified VM option")
 99                 .shouldHaveExitValue(1);
100         }
101     }
102 }