< prev index next >

src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java

Print this page




  35 import java.lang.module.ModuleDescriptor.Requires;
  36 import java.lang.module.ModuleDescriptor.Version;
  37 import java.util.ArrayList;
  38 import java.util.Collection;
  39 import java.util.EnumSet;
  40 import java.util.HashMap;
  41 import java.util.HashSet;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.Set;
  45 import java.util.TreeSet;
  46 import java.util.function.IntSupplier;
  47 
  48 import jdk.internal.module.Checks;
  49 import jdk.internal.module.ClassFileAttributes;
  50 import jdk.internal.module.ClassFileConstants;
  51 import jdk.internal.module.ModuleHashes;
  52 import jdk.internal.module.ModuleInfo.Attributes;
  53 import jdk.internal.module.ModuleInfoExtender;
  54 import jdk.internal.module.ModuleResolution;

  55 import jdk.internal.module.SystemModules;
  56 import jdk.internal.org.objectweb.asm.Attribute;
  57 import jdk.internal.org.objectweb.asm.ClassReader;
  58 import jdk.internal.org.objectweb.asm.ClassVisitor;
  59 import jdk.internal.org.objectweb.asm.ClassWriter;
  60 import jdk.internal.org.objectweb.asm.MethodVisitor;
  61 import jdk.internal.org.objectweb.asm.Opcodes;
  62 
  63 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  64 
  65 import jdk.tools.jlink.internal.ModuleSorter;
  66 import jdk.tools.jlink.plugin.PluginException;
  67 import jdk.tools.jlink.plugin.ResourcePool;
  68 import jdk.tools.jlink.plugin.Plugin;
  69 import jdk.tools.jlink.plugin.ResourcePoolBuilder;
  70 import jdk.tools.jlink.plugin.ResourcePoolEntry;
  71 
  72 /**
  73  * Jlink plugin to reconstitute module descriptors for system modules.
  74  * It will extend module-info.class with ModulePackages attribute,


 189         private ModuleDescriptor descriptor;  // may be different that the original one
 190 
 191         ModuleInfo(byte[] bytes, Set<String> packages, boolean dropModuleTarget)
 192             throws IOException
 193         {
 194             this.bain = new ByteArrayInputStream(bytes);
 195             this.packages = packages;
 196             this.attrs = jdk.internal.module.ModuleInfo.read(bain, null);
 197             // If ModulePackages attribute is present, the packages from this
 198             // module descriptor returns the packages in that attribute.
 199             // If it's not present, ModuleDescriptor::packages only contains
 200             // the exported and open packages from module-info.class
 201             this.descriptor = attrs.descriptor();
 202             if (descriptor.isAutomatic()) {
 203                 throw new InternalError("linking automatic module is not supported");
 204             }
 205 
 206             // add ModulePackages attribute if this module contains some packages
 207             // and ModulePackages is not present
 208             this.addModulePackages = packages.size() > 0 && !hasModulePackages();

 209             // drop target attribute only if any OS property is present
 210             if (dropModuleTarget) {
 211                 this.dropModuleTarget =
 212                     descriptor.osName().isPresent() ||
 213                     descriptor.osArch().isPresent() ||
 214                     descriptor.osVersion().isPresent();
 215             } else {
 216                 this.dropModuleTarget = false;
 217             }
 218         }
 219 
 220         String moduleName() {
 221             return attrs.descriptor().name();
 222         }
 223 
 224         ModuleDescriptor descriptor() {
 225             return descriptor;
 226         }
 227 
 228 
 229         Set<String> packages() {
 230             return packages;
 231         }
 232 




 233         ModuleHashes recordedHashes() {
 234             return attrs.recordedHashes();
 235         }
 236 
 237         ModuleResolution moduleResolution() {
 238             return attrs.moduleResolution();
 239         }
 240 
 241         /**
 242          * Validates names in ModuleDescriptor
 243          */
 244         void validateNames() {
 245             Checks.requireModuleName(descriptor.name());
 246             for (Requires req : descriptor.requires()) {
 247                 Checks.requireModuleName(req.name());
 248             }
 249             for (Exports e : descriptor.exports()) {
 250                 Checks.requirePackageName(e.source());
 251                 if (e.isQualified())
 252                     e.targets().forEach(Checks::requireModuleName);


 355          */
 356         InputStream getInputStream() {
 357             bain.reset();
 358             return bain;
 359         }
 360 
 361         class ModuleInfoRewriter extends ByteArrayOutputStream {
 362             final ModuleInfoExtender extender;
 363             ModuleInfoRewriter(InputStream in) {
 364                 this.extender = ModuleInfoExtender.newExtender(in);
 365             }
 366 
 367             void addModulePackages(Set<String> packages) {
 368                 // Add ModulePackages attribute
 369                 if (packages.size() > 0) {
 370                     extender.packages(packages);
 371                 }
 372             }
 373 
 374             void dropModuleTarget() {
 375                 extender.targetPlatform("", "", "");
 376             }
 377 
 378             byte[] getBytes() throws IOException {
 379                 extender.write(this);
 380                 return buf;
 381             }
 382         }
 383     }
 384 
 385     /**
 386      * ClassWriter of a new jdk.internal.module.SystemModules class
 387      * to reconstitute ModuleDescriptor of the system modules.
 388      */
 389     static class SystemModulesClassGenerator {
 390         private static final String CLASSNAME =
 391             "jdk/internal/module/SystemModules";
 392         private static final String MODULE_DESCRIPTOR_BUILDER =
 393             "jdk/internal/module/Builder";
 394         private static final String MODULE_DESCRIPTOR_ARRAY_SIGNATURE =
 395             "[Ljava/lang/module/ModuleDescriptor;";
 396         private static final String REQUIRES_MODIFIER_CLASSNAME =
 397             "java/lang/module/ModuleDescriptor$Requires$Modifier";
 398         private static final String EXPORTS_MODIFIER_CLASSNAME =
 399             "java/lang/module/ModuleDescriptor$Exports$Modifier";
 400         private static final String OPENS_MODIFIER_CLASSNAME =
 401             "java/lang/module/ModuleDescriptor$Opens$Modifier";




 402         private static final String MODULE_HASHES_ARRAY_SIGNATURE  =
 403             "[Ljdk/internal/module/ModuleHashes;";
 404         private static final String MODULE_RESOLUTION_CLASSNAME  =
 405             "jdk/internal/module/ModuleResolution";
 406         private static final String MODULE_RESOLUTIONS_ARRAY_SIGNATURE  =
 407             "[Ljdk/internal/module/ModuleResolution;";
 408 
 409         // static variables in SystemModules class
 410         private static final String MODULE_NAMES = "MODULE_NAMES";
 411         private static final String PACKAGE_COUNT = "PACKAGES_IN_BOOT_LAYER";
 412 
 413         private static final int MAX_LOCAL_VARS = 256;
 414 
 415         private final int BUILDER_VAR    = 0;
 416         private final int MD_VAR         = 1;  // variable for ModuleDescriptor

 417         private final int MH_VAR         = 1;  // variable for ModuleHashes
 418         private int nextLocalVar         = 2;  // index to next local variable
 419 
 420         private final ClassWriter cw;
 421         private boolean dropModuleTarget;
 422 
 423         // Method visitor for generating the SystemModules::modules() method
 424         private MethodVisitor mv;
 425 
 426         // list of all ModuleDescriptorBuilders, invoked in turn when building.
 427         private final List<ModuleInfo> moduleInfos = new ArrayList<>();
 428 
 429         // A builder to create one single Set instance for a given set of
 430         // names or modifiers to reduce the footprint
 431         // e.g. target modules of qualified exports
 432         private final DedupSetBuilder dedupSetBuilder
 433             = new DedupSetBuilder(this::getNextLocalVar);
 434 
 435         public SystemModulesClassGenerator(boolean retainModuleTarget) {
 436             this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS +


 498 
 499         }
 500 
 501         /*
 502          * Adds the given ModuleDescriptor to the system module list.
 503          * It performs link-time validation and prepares mapping from various
 504          * Sets to SetBuilders to emit an optimized number of sets during build.
 505          */
 506         public ResourcePoolEntry buildModuleInfo(ResourcePoolEntry entry,
 507                                                  Set<String> packages)
 508             throws IOException
 509         {
 510             if (moduleInfos.isEmpty() && !entry.moduleName().equals("java.base")) {
 511                 throw new InternalError("java.base must be the first module to process");
 512             }
 513 
 514             ModuleInfo moduleInfo;
 515             if (entry.moduleName().equals("java.base")) {
 516                 moduleInfo = new ModuleInfo(entry.contentBytes(), packages, false);
 517                 ModuleDescriptor md = moduleInfo.descriptor;
 518                 // drop Moduletarget attribute only if java.base has all OS properties
 519                 // otherwise, retain it
 520                 if (dropModuleTarget &&
 521                         md.osName().isPresent() && md.osArch().isPresent() &&
 522                         md.osVersion().isPresent()) {
 523                     dropModuleTarget = true;
 524                 } else {
 525                     dropModuleTarget = false;
 526                 }
 527             } else {
 528                 moduleInfo = new ModuleInfo(entry.contentBytes(), packages, dropModuleTarget);
 529             }
 530 
 531             // link-time validation
 532             moduleInfo.validateNames();
 533             // check if any exported or open package is not present
 534             moduleInfo.validatePackages();
 535 
 536             // module-info.class may be overridden for optimization
 537             // 1. update ModuleTarget attribute to drop osName, osArch, osVersion
 538             // 2. add/update ModulePackages attribute
 539             if (moduleInfo.shouldRewrite()) {
 540                 entry = entry.copyWithContent(moduleInfo.getBytes());
 541             }
 542             moduleInfos.add(moduleInfo);


 567         }
 568 
 569         /*
 570          * Generate bytecode for SystemModules
 571          */
 572         public ClassWriter getClassWriter() {
 573             int numModules = moduleInfos.size();
 574             Set<String> allPackages = new HashSet<>();
 575             int packageCount = 0;
 576             for (ModuleInfo minfo : moduleInfos) {
 577                 allPackages.addAll(minfo.packages);
 578                 packageCount += minfo.packages.size();
 579             }
 580 
 581             int numPackages = allPackages.size();
 582             boolean hasSplitPackages = (numPackages < packageCount);
 583             clinit(numModules, numPackages, hasSplitPackages);
 584 
 585             // generate SystemModules::descriptors
 586             genDescriptorsMethod();




 587             // generate SystemModules::hashes
 588             genHashesMethod();

 589             // generate SystemModules::moduleResolutions
 590             genModuleResolutionsMethod();
 591 
 592             return cw;
 593         }
 594 
 595         /*
 596          * Generate bytecode for SystemModules::descriptors method
 597          */
 598         private void genDescriptorsMethod() {
 599             this.mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
 600                                      "descriptors",
 601                                      "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE,
 602                                      "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE,
 603                                      null);
 604             mv.visitCode();
 605             pushInt(mv, moduleInfos.size());
 606             mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor");
 607             mv.visitVarInsn(ASTORE, MD_VAR);
 608 
 609             for (int index = 0; index < moduleInfos.size(); index++) {
 610                 ModuleInfo minfo = moduleInfos.get(index);
 611                 new ModuleDescriptorBuilder(minfo.descriptor(),
 612                                             minfo.packages(),
 613                                             index).build();
 614             }
 615             mv.visitVarInsn(ALOAD, MD_VAR);
 616             mv.visitInsn(ARETURN);
 617             mv.visitMaxs(0, 0);
 618             mv.visitEnd();

 619 






























 620         }
 621 
 622         /*






 623          * Generate bytecode for SystemModules::hashes method
 624          */
 625         private void genHashesMethod() {
 626             MethodVisitor hmv =
 627                 cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
 628                                "hashes",
 629                                "()" + MODULE_HASHES_ARRAY_SIGNATURE,
 630                                "()" + MODULE_HASHES_ARRAY_SIGNATURE,
 631                                null);
 632             hmv.visitCode();
 633             pushInt(hmv, moduleInfos.size());
 634             hmv.visitTypeInsn(ANEWARRAY, "jdk/internal/module/ModuleHashes");
 635             hmv.visitVarInsn(ASTORE, MH_VAR);
 636 
 637             for (int index = 0; index < moduleInfos.size(); index++) {
 638                 ModuleInfo minfo = moduleInfos.get(index);
 639                 if (minfo.recordedHashes() != null) {
 640                     new ModuleHashesBuilder(minfo.recordedHashes(),
 641                                             index,
 642                                             hmv).build();
 643                 }
 644             }
 645 
 646             hmv.visitVarInsn(ALOAD, MH_VAR);
 647             hmv.visitInsn(ARETURN);
 648             hmv.visitMaxs(0, 0);
 649             hmv.visitEnd();
 650 
 651         }
 652 
 653         /*
 654          * Generate bytecode for SystemModules::methodResoultions method
 655          */
 656         private void genModuleResolutionsMethod() {
 657             MethodVisitor mresmv =
 658                 cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
 659                                "moduleResolutions",
 660                                "()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE,
 661                                "()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE,
 662                                null);
 663             mresmv.visitCode();
 664             pushInt(mresmv, moduleInfos.size());
 665             mresmv.visitTypeInsn(ANEWARRAY, MODULE_RESOLUTION_CLASSNAME);
 666             mresmv.visitVarInsn(ASTORE, 0);
 667 
 668             for (int index=0; index < moduleInfos.size(); index++) {
 669                 ModuleInfo minfo = moduleInfos.get(index);
 670                 if (minfo.moduleResolution() != null) {
 671                     mresmv.visitVarInsn(ALOAD, 0);
 672                     pushInt(mresmv, index);
 673                     mresmv.visitTypeInsn(NEW, MODULE_RESOLUTION_CLASSNAME);


 732             static final String REQUIRES_SET_STRING_STRING_SIG =
 733                 "(Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;)" + REQUIRES_TYPE;
 734 
 735             // method signature for Builder instance methods that
 736             // return this Builder instance
 737             static final String EXPORTS_ARRAY_SIG =
 738                 "([" + EXPORTS_TYPE + ")" + BUILDER_TYPE;
 739             static final String OPENS_ARRAY_SIG =
 740                 "([" + OPENS_TYPE + ")" + BUILDER_TYPE;
 741             static final String PROVIDES_ARRAY_SIG =
 742                 "([" + PROVIDES_TYPE + ")" + BUILDER_TYPE;
 743             static final String REQUIRES_ARRAY_SIG =
 744                 "([" + REQUIRES_TYPE + ")" + BUILDER_TYPE;
 745             static final String SET_SIG = "(Ljava/util/Set;)" + BUILDER_TYPE;
 746             static final String STRING_SIG = "(Ljava/lang/String;)" + BUILDER_TYPE;
 747             static final String BOOLEAN_SIG = "(Z)" + BUILDER_TYPE;
 748 
 749             final ModuleDescriptor md;
 750             final Set<String> packages;
 751             final int index;

 752             ModuleDescriptorBuilder(ModuleDescriptor md, Set<String> packages, int index) {
 753                 if (md.isAutomatic()) {
 754                     throw new InternalError("linking automatic module is not supported");
 755                 }
 756                 this.md = md;
 757                 this.packages = packages;
 758                 this.index = index;
 759             }
 760 
 761             void build() {
 762                 // new jdk.internal.module.Builder
 763                 newBuilder();
 764 
 765                 // requires
 766                 requires(md.requires());
 767 
 768                 // exports
 769                 exports(md.exports());
 770 
 771                 // opens
 772                 opens(md.opens());
 773 
 774                 // uses
 775                 uses(md.uses());
 776 
 777                 // provides
 778                 provides(md.provides());
 779 
 780                 // all packages
 781                 packages(packages);
 782 
 783                 // version
 784                 md.version().ifPresent(this::version);
 785 
 786                 // main class
 787                 md.mainClass().ifPresent(this::mainClass);
 788 
 789                 // os name, arch, version
 790                 targetPlatform(md.osName().orElse(null),
 791                                md.osArch().orElse(null),
 792                                md.osVersion().orElse(null));
 793 
 794                 putModuleDescriptor();
 795             }
 796 
 797             void newBuilder() {
 798                 mv.visitTypeInsn(NEW, MODULE_DESCRIPTOR_BUILDER);
 799                 mv.visitInsn(DUP);
 800                 mv.visitLdcInsn(md.name());
 801                 mv.visitMethodInsn(INVOKESPECIAL, MODULE_DESCRIPTOR_BUILDER,
 802                     "<init>", "(Ljava/lang/String;)V", false);
 803                 mv.visitVarInsn(ASTORE, BUILDER_VAR);
 804                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
 805 
 806                 if (md.isOpen()) {
 807                     setModuleBit("open", true);
 808                 }
 809                 if (md.modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) {
 810                     setModuleBit("synthetic", true);
 811                 }
 812                 if (md.modifiers().contains(ModuleDescriptor.Modifier.MANDATED)) {
 813                     setModuleBit("mandated", true);


1071              */
1072             void mainClass(String cn) {
1073                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
1074                 mv.visitLdcInsn(cn);
1075                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
1076                     "mainClass", STRING_SIG, false);
1077                 mv.visitInsn(POP);
1078             }
1079 
1080             /*
1081              * Invoke Builder.version(Version v);
1082              */
1083             void version(Version v) {
1084                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
1085                 mv.visitLdcInsn(v.toString());
1086                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
1087                     "version", STRING_SIG, false);
1088                 mv.visitInsn(POP);
1089             }
1090 
1091             /*
1092              * Invoke Builder.osName(String name)
1093              *        Builder.osArch(String arch)
1094              *        Builder.osVersion(String version)
1095              */
1096             void targetPlatform(String osName, String osArch, String osVersion) {
1097                 if (osName != null) {
1098                     invokeBuilderMethod("osName", osName);
1099                 }
1100 
1101                 if (osArch != null) {
1102                     invokeBuilderMethod("osArch", osArch);
1103                 }
1104 
1105                 if (osVersion != null) {
1106                     invokeBuilderMethod("osVersion", osVersion);
1107                 }
1108             }
1109 
1110             void invokeBuilderMethod(String methodName, String value) {
1111                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
1112                 mv.visitLdcInsn(value);
1113                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
1114                     methodName, STRING_SIG, false);
1115                 mv.visitInsn(POP);
1116             }
1117         }
1118 
1119         class ModuleHashesBuilder {
1120             private static final String MODULE_HASHES_BUILDER =
1121                 "jdk/internal/module/ModuleHashes$Builder";
1122             private static final String MODULE_HASHES_BUILDER_TYPE =
1123                 "L" + MODULE_HASHES_BUILDER + ";";
1124             static final String STRING_BYTE_ARRAY_SIG =
1125                 "(Ljava/lang/String;[B)" + MODULE_HASHES_BUILDER_TYPE;
1126 
1127             final ModuleHashes recordedHashes;
1128             final MethodVisitor hmv;
1129             final int index;




  35 import java.lang.module.ModuleDescriptor.Requires;
  36 import java.lang.module.ModuleDescriptor.Version;
  37 import java.util.ArrayList;
  38 import java.util.Collection;
  39 import java.util.EnumSet;
  40 import java.util.HashMap;
  41 import java.util.HashSet;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.Set;
  45 import java.util.TreeSet;
  46 import java.util.function.IntSupplier;
  47 
  48 import jdk.internal.module.Checks;
  49 import jdk.internal.module.ClassFileAttributes;
  50 import jdk.internal.module.ClassFileConstants;
  51 import jdk.internal.module.ModuleHashes;
  52 import jdk.internal.module.ModuleInfo.Attributes;
  53 import jdk.internal.module.ModuleInfoExtender;
  54 import jdk.internal.module.ModuleResolution;
  55 import jdk.internal.module.ModuleTarget;
  56 import jdk.internal.module.SystemModules;
  57 import jdk.internal.org.objectweb.asm.Attribute;
  58 import jdk.internal.org.objectweb.asm.ClassReader;
  59 import jdk.internal.org.objectweb.asm.ClassVisitor;
  60 import jdk.internal.org.objectweb.asm.ClassWriter;
  61 import jdk.internal.org.objectweb.asm.MethodVisitor;
  62 import jdk.internal.org.objectweb.asm.Opcodes;
  63 
  64 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  65 
  66 import jdk.tools.jlink.internal.ModuleSorter;
  67 import jdk.tools.jlink.plugin.PluginException;
  68 import jdk.tools.jlink.plugin.ResourcePool;
  69 import jdk.tools.jlink.plugin.Plugin;
  70 import jdk.tools.jlink.plugin.ResourcePoolBuilder;
  71 import jdk.tools.jlink.plugin.ResourcePoolEntry;
  72 
  73 /**
  74  * Jlink plugin to reconstitute module descriptors for system modules.
  75  * It will extend module-info.class with ModulePackages attribute,


 190         private ModuleDescriptor descriptor;  // may be different that the original one
 191 
 192         ModuleInfo(byte[] bytes, Set<String> packages, boolean dropModuleTarget)
 193             throws IOException
 194         {
 195             this.bain = new ByteArrayInputStream(bytes);
 196             this.packages = packages;
 197             this.attrs = jdk.internal.module.ModuleInfo.read(bain, null);
 198             // If ModulePackages attribute is present, the packages from this
 199             // module descriptor returns the packages in that attribute.
 200             // If it's not present, ModuleDescriptor::packages only contains
 201             // the exported and open packages from module-info.class
 202             this.descriptor = attrs.descriptor();
 203             if (descriptor.isAutomatic()) {
 204                 throw new InternalError("linking automatic module is not supported");
 205             }
 206 
 207             // add ModulePackages attribute if this module contains some packages
 208             // and ModulePackages is not present
 209             this.addModulePackages = packages.size() > 0 && !hasModulePackages();
 210 
 211             // drop target attribute only if any OS property is present
 212             ModuleTarget target = attrs.target();
 213             if (dropModuleTarget && target != null) {
 214                 this.dropModuleTarget = (target.osName() != null)
 215                                         || (target.osArch() != null);

 216             } else {
 217                 this.dropModuleTarget = false;
 218             }
 219         }
 220 
 221         String moduleName() {
 222             return attrs.descriptor().name();
 223         }
 224 
 225         ModuleDescriptor descriptor() {
 226             return descriptor;
 227         }
 228 
 229 
 230         Set<String> packages() {
 231             return packages;
 232         }
 233 
 234         ModuleTarget target() {
 235             return attrs.target();
 236         }
 237 
 238         ModuleHashes recordedHashes() {
 239             return attrs.recordedHashes();
 240         }
 241 
 242         ModuleResolution moduleResolution() {
 243             return attrs.moduleResolution();
 244         }
 245 
 246         /**
 247          * Validates names in ModuleDescriptor
 248          */
 249         void validateNames() {
 250             Checks.requireModuleName(descriptor.name());
 251             for (Requires req : descriptor.requires()) {
 252                 Checks.requireModuleName(req.name());
 253             }
 254             for (Exports e : descriptor.exports()) {
 255                 Checks.requirePackageName(e.source());
 256                 if (e.isQualified())
 257                     e.targets().forEach(Checks::requireModuleName);


 360          */
 361         InputStream getInputStream() {
 362             bain.reset();
 363             return bain;
 364         }
 365 
 366         class ModuleInfoRewriter extends ByteArrayOutputStream {
 367             final ModuleInfoExtender extender;
 368             ModuleInfoRewriter(InputStream in) {
 369                 this.extender = ModuleInfoExtender.newExtender(in);
 370             }
 371 
 372             void addModulePackages(Set<String> packages) {
 373                 // Add ModulePackages attribute
 374                 if (packages.size() > 0) {
 375                     extender.packages(packages);
 376                 }
 377             }
 378 
 379             void dropModuleTarget() {
 380                 extender.targetPlatform("", "");
 381             }
 382 
 383             byte[] getBytes() throws IOException {
 384                 extender.write(this);
 385                 return buf;
 386             }
 387         }
 388     }
 389 
 390     /**
 391      * ClassWriter of a new jdk.internal.module.SystemModules class
 392      * to reconstitute ModuleDescriptor of the system modules.
 393      */
 394     static class SystemModulesClassGenerator {
 395         private static final String CLASSNAME =
 396             "jdk/internal/module/SystemModules";
 397         private static final String MODULE_DESCRIPTOR_BUILDER =
 398             "jdk/internal/module/Builder";
 399         private static final String MODULE_DESCRIPTOR_ARRAY_SIGNATURE =
 400             "[Ljava/lang/module/ModuleDescriptor;";
 401         private static final String REQUIRES_MODIFIER_CLASSNAME =
 402             "java/lang/module/ModuleDescriptor$Requires$Modifier";
 403         private static final String EXPORTS_MODIFIER_CLASSNAME =
 404             "java/lang/module/ModuleDescriptor$Exports$Modifier";
 405         private static final String OPENS_MODIFIER_CLASSNAME =
 406             "java/lang/module/ModuleDescriptor$Opens$Modifier";
 407         private static final String MODULE_TARGET_CLASSNAME  =
 408             "jdk/internal/module/ModuleTarget";
 409         private static final String MODULE_TARGET_ARRAY_SIGNATURE  =
 410             "[Ljdk/internal/module/ModuleTarget;";
 411         private static final String MODULE_HASHES_ARRAY_SIGNATURE  =
 412             "[Ljdk/internal/module/ModuleHashes;";
 413         private static final String MODULE_RESOLUTION_CLASSNAME  =
 414             "jdk/internal/module/ModuleResolution";
 415         private static final String MODULE_RESOLUTIONS_ARRAY_SIGNATURE  =
 416             "[Ljdk/internal/module/ModuleResolution;";
 417 
 418         // static variables in SystemModules class
 419         private static final String MODULE_NAMES = "MODULE_NAMES";
 420         private static final String PACKAGE_COUNT = "PACKAGES_IN_BOOT_LAYER";
 421 
 422         private static final int MAX_LOCAL_VARS = 256;
 423 
 424         private final int BUILDER_VAR    = 0;
 425         private final int MD_VAR         = 1;  // variable for ModuleDescriptor
 426         private final int MT_VAR         = 1;  // variable for ModuleTarget
 427         private final int MH_VAR         = 1;  // variable for ModuleHashes
 428         private int nextLocalVar         = 2;  // index to next local variable
 429 
 430         private final ClassWriter cw;
 431         private boolean dropModuleTarget;
 432 
 433         // Method visitor for generating the SystemModules::modules() method
 434         private MethodVisitor mv;
 435 
 436         // list of all ModuleDescriptorBuilders, invoked in turn when building.
 437         private final List<ModuleInfo> moduleInfos = new ArrayList<>();
 438 
 439         // A builder to create one single Set instance for a given set of
 440         // names or modifiers to reduce the footprint
 441         // e.g. target modules of qualified exports
 442         private final DedupSetBuilder dedupSetBuilder
 443             = new DedupSetBuilder(this::getNextLocalVar);
 444 
 445         public SystemModulesClassGenerator(boolean retainModuleTarget) {
 446             this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS +


 508 
 509         }
 510 
 511         /*
 512          * Adds the given ModuleDescriptor to the system module list.
 513          * It performs link-time validation and prepares mapping from various
 514          * Sets to SetBuilders to emit an optimized number of sets during build.
 515          */
 516         public ResourcePoolEntry buildModuleInfo(ResourcePoolEntry entry,
 517                                                  Set<String> packages)
 518             throws IOException
 519         {
 520             if (moduleInfos.isEmpty() && !entry.moduleName().equals("java.base")) {
 521                 throw new InternalError("java.base must be the first module to process");
 522             }
 523 
 524             ModuleInfo moduleInfo;
 525             if (entry.moduleName().equals("java.base")) {
 526                 moduleInfo = new ModuleInfo(entry.contentBytes(), packages, false);
 527                 ModuleDescriptor md = moduleInfo.descriptor;
 528                 // drop ModuleTarget attribute if java.base has all OS properties
 529                 ModuleTarget target = moduleInfo.target();
 530                 if (dropModuleTarget
 531                     && (target.osName() != null) && (target.osArch() != null)) {

 532                     dropModuleTarget = true;
 533                 } else {
 534                     dropModuleTarget = false;
 535                 }
 536             } else {
 537                 moduleInfo = new ModuleInfo(entry.contentBytes(), packages, dropModuleTarget);
 538             }
 539 
 540             // link-time validation
 541             moduleInfo.validateNames();
 542             // check if any exported or open package is not present
 543             moduleInfo.validatePackages();
 544 
 545             // module-info.class may be overridden for optimization
 546             // 1. update ModuleTarget attribute to drop osName, osArch, osVersion
 547             // 2. add/update ModulePackages attribute
 548             if (moduleInfo.shouldRewrite()) {
 549                 entry = entry.copyWithContent(moduleInfo.getBytes());
 550             }
 551             moduleInfos.add(moduleInfo);


 576         }
 577 
 578         /*
 579          * Generate bytecode for SystemModules
 580          */
 581         public ClassWriter getClassWriter() {
 582             int numModules = moduleInfos.size();
 583             Set<String> allPackages = new HashSet<>();
 584             int packageCount = 0;
 585             for (ModuleInfo minfo : moduleInfos) {
 586                 allPackages.addAll(minfo.packages);
 587                 packageCount += minfo.packages.size();
 588             }
 589 
 590             int numPackages = allPackages.size();
 591             boolean hasSplitPackages = (numPackages < packageCount);
 592             clinit(numModules, numPackages, hasSplitPackages);
 593 
 594             // generate SystemModules::descriptors
 595             genDescriptorsMethod();
 596 
 597             // generate SystemModules::targets
 598             genTargetsMethod();
 599 
 600             // generate SystemModules::hashes
 601             genHashesMethod();
 602 
 603             // generate SystemModules::moduleResolutions
 604             genModuleResolutionsMethod();
 605 
 606             return cw;
 607         }
 608 
 609         /**
 610          * Generate bytecode for SystemModules::descriptors method
 611          */
 612         private void genDescriptorsMethod() {
 613             this.mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
 614                                      "descriptors",
 615                                      "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE,
 616                                      "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE,
 617                                      null);
 618             mv.visitCode();
 619             pushInt(mv, moduleInfos.size());
 620             mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor");
 621             mv.visitVarInsn(ASTORE, MD_VAR);
 622 
 623             for (int index = 0; index < moduleInfos.size(); index++) {
 624                 ModuleInfo minfo = moduleInfos.get(index);
 625                 new ModuleDescriptorBuilder(minfo.descriptor(),
 626                                             minfo.packages(),
 627                                             index).build();
 628             }
 629             mv.visitVarInsn(ALOAD, MD_VAR);
 630             mv.visitInsn(ARETURN);
 631             mv.visitMaxs(0, 0);
 632             mv.visitEnd();
 633         }
 634 
 635         /**
 636          * Generate bytecode for SystemModules::targets method
 637          */
 638         private void genTargetsMethod() {
 639             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
 640                                               "targets",
 641                                               "()" + MODULE_TARGET_ARRAY_SIGNATURE,
 642                                               "()" + MODULE_TARGET_ARRAY_SIGNATURE,
 643                                               null);
 644             mv.visitCode();
 645             pushInt(mv, moduleInfos.size());
 646             mv.visitTypeInsn(ANEWARRAY, MODULE_TARGET_CLASSNAME);
 647             mv.visitVarInsn(ASTORE, MT_VAR);
 648 
 649             for (int index=0; index < moduleInfos.size(); index++) {
 650                 ModuleInfo minfo = moduleInfos.get(index);
 651                 if (minfo.target() != null && !minfo.dropModuleTarget) {
 652                     mv.visitVarInsn(ALOAD, MT_VAR);
 653                     pushInt(mv, index);
 654 
 655                     // new ModuleTarget(String, String)
 656                     mv.visitTypeInsn(NEW, MODULE_TARGET_CLASSNAME);
 657                     mv.visitInsn(DUP);
 658                     mv.visitLdcInsn(minfo.target().osName());
 659                     mv.visitLdcInsn(minfo.target().osArch());
 660                     mv.visitMethodInsn(INVOKESPECIAL, MODULE_TARGET_CLASSNAME,
 661                         "<init>", "(Ljava/lang/String;Ljava/lang/String;)V", false);
 662 
 663                     mv.visitInsn(AASTORE);
 664                 }
 665             }
 666 
 667             mv.visitVarInsn(ALOAD, MT_VAR);
 668             mv.visitInsn(ARETURN);
 669             mv.visitMaxs(0, 0);
 670             mv.visitEnd();
 671         }
 672 
 673         /**
 674          * Generate bytecode for SystemModules::hashes method
 675          */
 676         private void genHashesMethod() {
 677             MethodVisitor hmv =
 678                 cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
 679                                "hashes",
 680                                "()" + MODULE_HASHES_ARRAY_SIGNATURE,
 681                                "()" + MODULE_HASHES_ARRAY_SIGNATURE,
 682                                null);
 683             hmv.visitCode();
 684             pushInt(hmv, moduleInfos.size());
 685             hmv.visitTypeInsn(ANEWARRAY, "jdk/internal/module/ModuleHashes");
 686             hmv.visitVarInsn(ASTORE, MH_VAR);
 687 
 688             for (int index = 0; index < moduleInfos.size(); index++) {
 689                 ModuleInfo minfo = moduleInfos.get(index);
 690                 if (minfo.recordedHashes() != null) {
 691                     new ModuleHashesBuilder(minfo.recordedHashes(),
 692                                             index,
 693                                             hmv).build();
 694                 }
 695             }
 696 
 697             hmv.visitVarInsn(ALOAD, MH_VAR);
 698             hmv.visitInsn(ARETURN);
 699             hmv.visitMaxs(0, 0);
 700             hmv.visitEnd();

 701         }
 702 
 703         /**
 704          * Generate bytecode for SystemModules::methodResoultions method
 705          */
 706         private void genModuleResolutionsMethod() {
 707             MethodVisitor mresmv =
 708                 cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
 709                                "moduleResolutions",
 710                                "()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE,
 711                                "()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE,
 712                                null);
 713             mresmv.visitCode();
 714             pushInt(mresmv, moduleInfos.size());
 715             mresmv.visitTypeInsn(ANEWARRAY, MODULE_RESOLUTION_CLASSNAME);
 716             mresmv.visitVarInsn(ASTORE, 0);
 717 
 718             for (int index=0; index < moduleInfos.size(); index++) {
 719                 ModuleInfo minfo = moduleInfos.get(index);
 720                 if (minfo.moduleResolution() != null) {
 721                     mresmv.visitVarInsn(ALOAD, 0);
 722                     pushInt(mresmv, index);
 723                     mresmv.visitTypeInsn(NEW, MODULE_RESOLUTION_CLASSNAME);


 782             static final String REQUIRES_SET_STRING_STRING_SIG =
 783                 "(Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;)" + REQUIRES_TYPE;
 784 
 785             // method signature for Builder instance methods that
 786             // return this Builder instance
 787             static final String EXPORTS_ARRAY_SIG =
 788                 "([" + EXPORTS_TYPE + ")" + BUILDER_TYPE;
 789             static final String OPENS_ARRAY_SIG =
 790                 "([" + OPENS_TYPE + ")" + BUILDER_TYPE;
 791             static final String PROVIDES_ARRAY_SIG =
 792                 "([" + PROVIDES_TYPE + ")" + BUILDER_TYPE;
 793             static final String REQUIRES_ARRAY_SIG =
 794                 "([" + REQUIRES_TYPE + ")" + BUILDER_TYPE;
 795             static final String SET_SIG = "(Ljava/util/Set;)" + BUILDER_TYPE;
 796             static final String STRING_SIG = "(Ljava/lang/String;)" + BUILDER_TYPE;
 797             static final String BOOLEAN_SIG = "(Z)" + BUILDER_TYPE;
 798 
 799             final ModuleDescriptor md;
 800             final Set<String> packages;
 801             final int index;
 802 
 803             ModuleDescriptorBuilder(ModuleDescriptor md, Set<String> packages, int index) {
 804                 if (md.isAutomatic()) {
 805                     throw new InternalError("linking automatic module is not supported");
 806                 }
 807                 this.md = md;
 808                 this.packages = packages;
 809                 this.index = index;
 810             }
 811 
 812             void build() {
 813                 // new jdk.internal.module.Builder
 814                 newBuilder();
 815 
 816                 // requires
 817                 requires(md.requires());
 818 
 819                 // exports
 820                 exports(md.exports());
 821 
 822                 // opens
 823                 opens(md.opens());
 824 
 825                 // uses
 826                 uses(md.uses());
 827 
 828                 // provides
 829                 provides(md.provides());
 830 
 831                 // all packages
 832                 packages(packages);
 833 
 834                 // version
 835                 md.version().ifPresent(this::version);
 836 
 837                 // main class
 838                 md.mainClass().ifPresent(this::mainClass);
 839 





 840                 putModuleDescriptor();
 841             }
 842 
 843             void newBuilder() {
 844                 mv.visitTypeInsn(NEW, MODULE_DESCRIPTOR_BUILDER);
 845                 mv.visitInsn(DUP);
 846                 mv.visitLdcInsn(md.name());
 847                 mv.visitMethodInsn(INVOKESPECIAL, MODULE_DESCRIPTOR_BUILDER,
 848                     "<init>", "(Ljava/lang/String;)V", false);
 849                 mv.visitVarInsn(ASTORE, BUILDER_VAR);
 850                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
 851 
 852                 if (md.isOpen()) {
 853                     setModuleBit("open", true);
 854                 }
 855                 if (md.modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) {
 856                     setModuleBit("synthetic", true);
 857                 }
 858                 if (md.modifiers().contains(ModuleDescriptor.Modifier.MANDATED)) {
 859                     setModuleBit("mandated", true);


1117              */
1118             void mainClass(String cn) {
1119                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
1120                 mv.visitLdcInsn(cn);
1121                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
1122                     "mainClass", STRING_SIG, false);
1123                 mv.visitInsn(POP);
1124             }
1125 
1126             /*
1127              * Invoke Builder.version(Version v);
1128              */
1129             void version(Version v) {
1130                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
1131                 mv.visitLdcInsn(v.toString());
1132                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
1133                     "version", STRING_SIG, false);
1134                 mv.visitInsn(POP);
1135             }
1136 



















1137             void invokeBuilderMethod(String methodName, String value) {
1138                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
1139                 mv.visitLdcInsn(value);
1140                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
1141                     methodName, STRING_SIG, false);
1142                 mv.visitInsn(POP);
1143             }
1144         }
1145 
1146         class ModuleHashesBuilder {
1147             private static final String MODULE_HASHES_BUILDER =
1148                 "jdk/internal/module/ModuleHashes$Builder";
1149             private static final String MODULE_HASHES_BUILDER_TYPE =
1150                 "L" + MODULE_HASHES_BUILDER + ";";
1151             static final String STRING_BYTE_ARRAY_SIG =
1152                 "(Ljava/lang/String;[B)" + MODULE_HASHES_BUILDER_TYPE;
1153 
1154             final ModuleHashes recordedHashes;
1155             final MethodVisitor hmv;
1156             final int index;


< prev index next >