1 /*
   2  * Copyright (c) 2018, 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 import java.io.File;
  26 import java.lang.module.Configuration;
  27 import java.lang.module.ModuleDescriptor;
  28 import java.util.List;
  29 import java.util.Set;
  30 import sun.hotspot.WhiteBox;
  31 
  32 //
  33 // Test archived system module graph when open archive heap objects are mapped:
  34 //
  35 public class CheckArchivedModuleApp {
  36     static WhiteBox wb;
  37     public static void main(String args[]) throws Exception {
  38         wb = WhiteBox.getWhiteBox();
  39 
  40         if (!wb.areOpenArchiveHeapObjectsMapped()) {
  41             System.out.println("Archived open_archive_heap objects are not mapped.");
  42             System.out.println("This may happen during normal operation. Test Skipped.");
  43             return;
  44         }
  45 
  46         if (args.length != 2) {
  47            throw new RuntimeException(
  48                "FAILED. Incorrect argument length: " + args.length);
  49         }
  50 
  51         boolean expectArchivedDescriptors = "yes".equals(args[0]);
  52         boolean expectArchivedConfiguration = "yes".equals(args[1]);
  53         // -XX:+EnableJVMCI adds extra system modules, in which case the system
  54         // module objects are not archived.
  55         Boolean enableJVMCI = wb.getBooleanVMFlag("EnableJVMCI");
  56         if (enableJVMCI != null && enableJVMCI) {
  57             expectArchivedDescriptors = false;
  58             expectArchivedConfiguration = false;
  59         }
  60 
  61         checkModuleDescriptors(expectArchivedDescriptors);
  62         checkConfiguration(expectArchivedConfiguration);
  63         checkEmptyConfiguration(expectArchivedConfiguration);
  64     }
  65 
  66     private static void checkModuleDescriptors(boolean expectArchivedDescriptors) {
  67         Set<Module> modules = ModuleLayer.boot().modules();
  68         for (Module m : modules) {
  69             ModuleDescriptor md = m.getDescriptor();
  70             String name = md.name();
  71             if (expectArchivedDescriptors) {
  72                 if (wb.isShared(md)) {
  73                     System.out.println(name + " is archived. Expected.");
  74                 } else {
  75                     throw new RuntimeException(
  76                         "FAILED. " + name + " is not archived. Expect archived.");
  77                 }
  78             } else {
  79                 if (!wb.isShared(md)) {
  80                     System.out.println(name + " is not archived. Expected.");
  81                 } else {
  82                     throw new RuntimeException(
  83                         "FAILED. " + name + " is archived. Expect not archived.");
  84                 }
  85             }
  86         }
  87     }
  88 
  89     private static void checkEmptyConfiguration(boolean expectArchivedConfiguration) {
  90         // Configuration.EMPTY_CONFIGURATION uses the singletons,
  91         // ListN.EMPTY_LIST, SetN.EMPTY_SET and MapN.EMPTY_MAP in
  92         // ImmutableCollections for the 'parents', 'modules' and
  93         // 'graph' fields. The ImmutableCollections singletons
  94         // can be accessed via List.of(), Set.of() and Map.of() APIs.
  95         // Configuration public APIs also allow access to the
  96         // EMPTY_CONFIGURATION's 'parents' and 'modules'. When the
  97         // archived java heap data is enabled at runtime, make sure
  98         // the EMPTY_CONFIGURATION.parents and EMPTY_CONFIGURATION.modules
  99         // are the archived ImmutableCollections singletons.
 100         Configuration emptyCf = Configuration.empty();
 101         List emptyCfParents = emptyCf.parents();
 102         Set emptyCfModules = emptyCf.modules();
 103         if (expectArchivedConfiguration) {
 104             if (emptyCfParents == List.of() &&
 105                 wb.isShared(emptyCfParents)) {
 106                 System.out.println("Empty Configuration has expected parents.");
 107             } else {
 108                 throw new RuntimeException(
 109                     "FAILED. Unexpected parents for empty Configuration.");
 110             }
 111             if (emptyCfModules == Set.of() &&
 112                 wb.isShared(emptyCfModules)) {
 113                 System.out.println("Empty Configuration has expected module set.");
 114             } else {
 115                 throw new RuntimeException(
 116                     "FAILED. Unexpected module set for empty Configuration.");
 117             }
 118         }
 119     }
 120 
 121 
 122 
 123     private static void checkConfiguration(boolean expectArchivedConfiguration) {
 124         Configuration cf = ModuleLayer.boot().configuration();
 125 
 126         if (expectArchivedConfiguration) {
 127             if (wb.isShared(cf)) {
 128                 System.out.println("Boot layer configuration is archived. Expected.");
 129             } else {
 130                 throw new RuntimeException(
 131                     "FAILED. Boot layer configuration is not archived.");
 132             }
 133         } else {
 134             if (!wb.isShared(cf)) {
 135                 System.out.println("Boot layer configuration is not archived. Expected.");
 136             } else {
 137                 throw new RuntimeException(
 138                     "FAILED. Boot layer configuration is archived.");
 139             }
 140         }
 141     }
 142 }