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;
|