< prev index next >

src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java

Print this page




  51 
  52 /**
  53  * Provides ASM implementations of {@code Attribute} to read and write the
  54  * class file attributes in a module-info class file.
  55  */
  56 
  57 public final class ClassFileAttributes {
  58 
  59     private ClassFileAttributes() { }
  60 
  61     /**
  62      * Module_attribute {
  63      *   // See lang-vm.html for details.
  64      * }
  65      */
  66     public static class ModuleAttribute extends Attribute {
  67         private static final JavaLangModuleAccess JLMA
  68             = SharedSecrets.getJavaLangModuleAccess();
  69 
  70         private ModuleDescriptor descriptor;

  71 
  72         public ModuleAttribute(ModuleDescriptor descriptor) {
  73             super(MODULE);
  74             this.descriptor = descriptor;
  75         }
  76 





  77         public ModuleAttribute() {
  78             super(MODULE);
  79         }
  80 
  81         @Override
  82         protected Attribute read(ClassReader cr,
  83                                  int off,
  84                                  int len,
  85                                  char[] buf,
  86                                  int codeOff,
  87                                  Label[] labels)
  88         {
  89             ModuleAttribute attr = new ModuleAttribute();
  90 
  91             // module_name
  92             String mn = cr.readUTF8(off, buf).replace('/', '.');
  93             off += 2;
  94 
  95             // module_flags
  96             int module_flags = cr.readUnsignedShort(off);
  97             boolean open = ((module_flags & ACC_OPEN) != 0);

  98             off += 2;
  99 
 100             ModuleDescriptor.Builder builder;
 101             if (open) {
 102                 builder = JLMA.newOpenModuleBuilder(mn, false);
 103             } else {
 104                 builder = JLMA.newModuleBuilder(mn, false);







 105             }
 106 
 107             // requires_count and requires[requires_count]
 108             int requires_count = cr.readUnsignedShort(off);
 109             off += 2;
 110             for (int i=0; i<requires_count; i++) {
 111                 String dn = cr.readUTF8(off, buf).replace('/', '.');
 112                 int flags = cr.readUnsignedShort(off + 2);





 113                 Set<Requires.Modifier> mods;
 114                 if (flags == 0) {
 115                     mods = Collections.emptySet();
 116                 } else {
 117                     mods = new HashSet<>();
 118                     if ((flags & ACC_TRANSITIVE) != 0)
 119                         mods.add(Requires.Modifier.TRANSITIVE);
 120                     if ((flags & ACC_STATIC_PHASE) != 0)
 121                         mods.add(Requires.Modifier.STATIC);
 122                     if ((flags & ACC_SYNTHETIC) != 0)
 123                         mods.add(Requires.Modifier.SYNTHETIC);
 124                     if ((flags & ACC_MANDATED) != 0)
 125                         mods.add(Requires.Modifier.MANDATED);
 126                 }











 127                 builder.requires(mods, dn);
 128                 off += 4;


 129             }
 130 
 131             // exports_count and exports[exports_count]
 132             int exports_count = cr.readUnsignedShort(off);
 133             off += 2;
 134             if (exports_count > 0) {
 135                 for (int i=0; i<exports_count; i++) {
 136                     String pkg = cr.readUTF8(off, buf).replace('/', '.');

 137                     off += 2;
 138 
 139                     int flags = cr.readUnsignedShort(off);
 140                     off += 2;
 141                     Set<Exports.Modifier> mods;
 142                     if (flags == 0) {
 143                         mods = Collections.emptySet();
 144                     } else {
 145                         mods = new HashSet<>();
 146                         if ((flags & ACC_SYNTHETIC) != 0)
 147                             mods.add(Exports.Modifier.SYNTHETIC);
 148                         if ((flags & ACC_MANDATED) != 0)
 149                             mods.add(Exports.Modifier.MANDATED);
 150                     }
 151 
 152                     int exports_to_count = cr.readUnsignedShort(off);
 153                     off += 2;
 154                     if (exports_to_count > 0) {
 155                         Set<String> targets = new HashSet<>();
 156                         for (int j=0; j<exports_to_count; j++) {
 157                             String t = cr.readUTF8(off, buf).replace('/', '.');
 158                             off += 2;
 159                             targets.add(t);
 160                         }
 161                         builder.exports(mods, pkg, targets);
 162                     } else {
 163                         builder.exports(mods, pkg);
 164                     }
 165                 }
 166             }
 167 
 168             // opens_count and opens[opens_count]
 169             int open_count = cr.readUnsignedShort(off);
 170             off += 2;
 171             if (open_count > 0) {
 172                 for (int i=0; i<open_count; i++) {
 173                     String pkg = cr.readUTF8(off, buf).replace('/', '.');

 174                     off += 2;
 175 
 176                     int flags = cr.readUnsignedShort(off);
 177                     off += 2;
 178                     Set<Opens.Modifier> mods;
 179                     if (flags == 0) {
 180                         mods = Collections.emptySet();
 181                     } else {
 182                         mods = new HashSet<>();
 183                         if ((flags & ACC_SYNTHETIC) != 0)
 184                             mods.add(Opens.Modifier.SYNTHETIC);
 185                         if ((flags & ACC_MANDATED) != 0)
 186                             mods.add(Opens.Modifier.MANDATED);
 187                     }
 188 
 189                     int opens_to_count = cr.readUnsignedShort(off);
 190                     off += 2;
 191                     if (opens_to_count > 0) {
 192                         Set<String> targets = new HashSet<>();
 193                         for (int j=0; j<opens_to_count; j++) {
 194                             String t = cr.readUTF8(off, buf).replace('/', '.');
 195                             off += 2;
 196                             targets.add(t);
 197                         }
 198                         builder.opens(mods, pkg, targets);
 199                     } else {
 200                         builder.opens(mods, pkg);
 201                     }
 202                 }
 203             }
 204 
 205             // uses_count and uses_index[uses_count]
 206             int uses_count = cr.readUnsignedShort(off);
 207             off += 2;
 208             if (uses_count > 0) {
 209                 for (int i=0; i<uses_count; i++) {
 210                     String sn = cr.readClass(off, buf).replace('/', '.');
 211                     builder.uses(sn);
 212                     off += 2;
 213                 }
 214             }
 215 
 216             // provides_count and provides[provides_count]
 217             int provides_count = cr.readUnsignedShort(off);
 218             off += 2;
 219             if (provides_count > 0) {
 220                 for (int i=0; i<provides_count; i++) {
 221                     String service = cr.readClass(off, buf).replace('/', '.');
 222                     off += 2;
 223                     int with_count = cr.readUnsignedShort(off);
 224                     off += 2;
 225                     List<String> providers = new ArrayList<>();
 226                     for (int j=0; j<with_count; j++) {
 227                         String cn = cr.readClass(off, buf).replace('/', '.');
 228                         off += 2;
 229                         providers.add(cn);
 230                     }
 231                     builder.provides(service, providers);
 232                 }
 233             }
 234 
 235             attr.descriptor = builder.build();
 236             return attr;
 237         }
 238 
 239         @Override
 240         protected ByteVector write(ClassWriter cw,
 241                                    byte[] code,
 242                                    int len,
 243                                    int maxStack,
 244                                    int maxLocals)
 245         {
 246             assert descriptor != null;
 247             ByteVector attr = new ByteVector();
 248 
 249             // module_name
 250             String mn = descriptor.name();
 251             int module_name_index = cw.newUTF8(mn.replace('.', '/'));
 252             attr.putShort(module_name_index);
 253 
 254             // module_flags
 255             int module_flags = 0;
 256             if (descriptor.isOpen())
 257                 module_flags |= ACC_OPEN;
 258             if (descriptor.isSynthetic())
 259                 module_flags |= ACC_SYNTHETIC;
 260             attr.putShort(module_flags);
 261 









 262             // requires_count
 263             attr.putShort(descriptor.requires().size());
 264 
 265             // requires[requires_count]
 266             for (Requires md : descriptor.requires()) {
 267                 String dn = md.name();
 268                 int flags = 0;
 269                 if (md.modifiers().contains(Requires.Modifier.TRANSITIVE))
 270                     flags |= ACC_TRANSITIVE;
 271                 if (md.modifiers().contains(Requires.Modifier.STATIC))
 272                     flags |= ACC_STATIC_PHASE;
 273                 if (md.modifiers().contains(Requires.Modifier.SYNTHETIC))
 274                     flags |= ACC_SYNTHETIC;
 275                 if (md.modifiers().contains(Requires.Modifier.MANDATED))
 276                     flags |= ACC_MANDATED;
 277                 int index = cw.newUTF8(dn.replace('.', '/'));
 278                 attr.putShort(index);
 279                 attr.putShort(flags);









 280             }
 281 
 282             // exports_count and exports[exports_count];
 283             attr.putShort(descriptor.exports().size());
 284             for (Exports e : descriptor.exports()) {
 285                 String pkg = e.source().replace('.', '/');
 286                 attr.putShort(cw.newUTF8(pkg));
 287 
 288                 int flags = 0;
 289                 if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
 290                     flags |= ACC_SYNTHETIC;
 291                 if (e.modifiers().contains(Exports.Modifier.MANDATED))
 292                     flags |= ACC_MANDATED;
 293                 attr.putShort(flags);
 294 
 295                 if (e.isQualified()) {
 296                     Set<String> ts = e.targets();
 297                     attr.putShort(ts.size());
 298                     ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
 299                 } else {
 300                     attr.putShort(0);
 301                 }
 302             }
 303 
 304 
 305             // opens_counts and opens[opens_counts]
 306             attr.putShort(descriptor.opens().size());
 307             for (Opens obj : descriptor.opens()) {
 308                 String pkg = obj.source().replace('.', '/');
 309                 attr.putShort(cw.newUTF8(pkg));
 310 
 311                 int flags = 0;
 312                 if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
 313                     flags |= ACC_SYNTHETIC;
 314                 if (obj.modifiers().contains(Opens.Modifier.MANDATED))
 315                     flags |= ACC_MANDATED;
 316                 attr.putShort(flags);
 317 
 318                 if (obj.isQualified()) {
 319                     Set<String> ts = obj.targets();
 320                     attr.putShort(ts.size());
 321                     ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
 322                 } else {
 323                     attr.putShort(0);
 324                 }
 325             }
 326 
 327             // uses_count and uses_index[uses_count]
 328             if (descriptor.uses().isEmpty()) {
 329                 attr.putShort(0);
 330             } else {
 331                 attr.putShort(descriptor.uses().size());
 332                 for (String s : descriptor.uses()) {
 333                     String service = s.replace('.', '/');
 334                     int index = cw.newClass(service);
 335                     attr.putShort(index);
 336                 }
 337             }
 338 
 339             // provides_count and provides[provides_count]
 340             if (descriptor.provides().isEmpty()) {
 341                 attr.putShort(0);


 352                 }
 353             }
 354 
 355             return attr;
 356         }
 357     }
 358 
 359     /**
 360      * ModulePackages attribute.
 361      *
 362      * <pre> {@code
 363      *
 364      * ModulePackages_attribute {
 365      *   // index to CONSTANT_utf8_info structure in constant pool representing
 366      *   // the string "ModulePackages"
 367      *   u2 attribute_name_index;
 368      *   u4 attribute_length;
 369      *
 370      *   // the number of entries in the packages table
 371      *   u2 packages_count;
 372      *   { // index to CONSTANT_CONSTANT_utf8_info structure with the package name
 373      *     u2 package_index
 374      *   } packages[package_count];
 375      *
 376      * }</pre>
 377      */
 378     public static class ModulePackagesAttribute extends Attribute {
 379         private final Set<String> packages;
 380 
 381         public ModulePackagesAttribute(Set<String> packages) {
 382             super(MODULE_PACKAGES);
 383             this.packages = packages;
 384         }
 385 
 386         public ModulePackagesAttribute() {
 387             this(null);
 388         }
 389 
 390         @Override
 391         protected Attribute read(ClassReader cr,
 392                                  int off,
 393                                  int len,
 394                                  char[] buf,
 395                                  int codeOff,
 396                                  Label[] labels)
 397         {
 398             // package count
 399             int package_count = cr.readUnsignedShort(off);
 400             off += 2;
 401 
 402             // packages
 403             Set<String> packages = new HashSet<>();
 404             for (int i=0; i<package_count; i++) {
 405                 String pkg = cr.readUTF8(off, buf).replace('/', '.');
 406                 packages.add(pkg);
 407                 off += 2;
 408             }
 409 
 410             return new ModulePackagesAttribute(packages);
 411         }
 412 
 413         @Override
 414         protected ByteVector write(ClassWriter cw,
 415                                    byte[] code,
 416                                    int len,
 417                                    int maxStack,
 418                                    int maxLocals)
 419         {
 420             assert packages != null;
 421 
 422             ByteVector attr = new ByteVector();
 423 
 424             // package_count
 425             attr.putShort(packages.size());
 426 
 427             // packages
 428             packages.stream()
 429                 .map(p -> p.replace('.', '/'))
 430                 .forEach(p -> attr.putShort(cw.newUTF8(p)));
 431 
 432             return attr;
 433         }
 434 
 435     }
 436 
 437     /**
 438      * ModuleVersion attribute.
 439      *
 440      * <pre> {@code
 441      *
 442      * ModuleVersion_attribute {
 443      *   // index to CONSTANT_utf8_info structure in constant pool representing
 444      *   // the string "ModuleVersion"
 445      *   u2 attribute_name_index;
 446      *   u4 attribute_length;
 447      *
 448      *   // index to CONSTANT_CONSTANT_utf8_info structure with the version
 449      *   u2 version_index;
 450      * }
 451      *
 452      * } </pre>
 453      */
 454     public static class ModuleVersionAttribute extends Attribute {
 455         private final Version version;
 456 
 457         public ModuleVersionAttribute(Version version) {
 458             super(MODULE_VERSION);
 459             this.version = version;
 460         }
 461 
 462         public ModuleVersionAttribute() {
 463             this(null);
 464         }
 465 
 466         @Override
 467         protected Attribute read(ClassReader cr,
 468                                  int off,
 469                                  int len,
 470                                  char[] buf,
 471                                  int codeOff,
 472                                  Label[] labels)
 473         {
 474             String value = cr.readUTF8(off, buf);
 475             return new ModuleVersionAttribute(Version.parse(value));
 476         }
 477 
 478         @Override
 479         protected ByteVector write(ClassWriter cw,
 480                                    byte[] code,
 481                                    int len,
 482                                    int maxStack,
 483                                    int maxLocals)
 484         {
 485             ByteVector attr = new ByteVector();
 486             int index = cw.newUTF8(version.toString());
 487             attr.putShort(index);
 488             return attr;
 489         }
 490     }
 491 
 492     /**
 493      * ModuleMainClass attribute.
 494      *
 495      * <pre> {@code
 496      *
 497      * MainClass_attribute {
 498      *   // index to CONSTANT_utf8_info structure in constant pool representing
 499      *   // the string "ModuleMainClass"
 500      *   u2 attribute_name_index;
 501      *   u4 attribute_length;
 502      *
 503      *   // index to CONSTANT_Class_info structure with the main class name
 504      *   u2 main_class_index;
 505      * }
 506      *
 507      * } </pre>
 508      */
 509     public static class ModuleMainClassAttribute extends Attribute {
 510         private final String mainClass;
 511 
 512         public ModuleMainClassAttribute(String mainClass) {
 513             super(MODULE_MAIN_CLASS);
 514             this.mainClass = mainClass;
 515         }
 516 
 517         public ModuleMainClassAttribute() {
 518             this(null);
 519         }
 520 
 521         @Override
 522         protected Attribute read(ClassReader cr,
 523                                  int off,
 524                                  int len,
 525                                  char[] buf,
 526                                  int codeOff,
 527                                  Label[] labels)
 528         {
 529             String value = cr.readClass(off, buf);
 530             return new ModuleMainClassAttribute(value);
 531         }
 532 
 533         @Override
 534         protected ByteVector write(ClassWriter cw,
 535                                    byte[] code,
 536                                    int len,
 537                                    int maxStack,
 538                                    int maxLocals)
 539         {
 540             ByteVector attr = new ByteVector();
 541             int index = cw.newClass(mainClass);
 542             attr.putShort(index);
 543             return attr;
 544         }
 545     }
 546 
 547     /**
 548      * ModuleTarget attribute.
 549      *
 550      * <pre> {@code
 551      *
 552      * TargetPlatform_attribute {
 553      *   // index to CONSTANT_utf8_info structure in constant pool representing
 554      *   // the string "ModuleTarget"
 555      *   u2 attribute_name_index;
 556      *   u4 attribute_length;
 557      *
 558      *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS name
 559      *   u2 os_name_index;
 560      *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS arch
 561      *   u2 os_arch_index
 562      *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS version
 563      *   u2 os_version_index;
 564      * }
 565      *
 566      * } </pre>
 567      */
 568     public static class ModuleTargetAttribute extends Attribute {
 569         private final String osName;
 570         private final String osArch;
 571         private final String osVersion;
 572 
 573         public ModuleTargetAttribute(String osName, String osArch, String osVersion) {
 574             super(MODULE_TARGET);
 575             this.osName = osName;
 576             this.osArch = osArch;
 577             this.osVersion = osVersion;
 578         }
 579 
 580         public ModuleTargetAttribute() {
 581             this(null, null, null);
 582         }


 639             return attr;
 640         }
 641     }
 642 
 643     /**
 644      * ModuleHashes attribute.
 645      *
 646      * <pre> {@code
 647      *
 648      * ModuleHashes_attribute {
 649      *   // index to CONSTANT_utf8_info structure in constant pool representing
 650      *   // the string "ModuleHashes"
 651      *   u2 attribute_name_index;
 652      *   u4 attribute_length;
 653      *
 654      *   // index to CONSTANT_utf8_info structure with algorithm name
 655      *   u2 algorithm_index;
 656      *
 657      *   // the number of entries in the hashes table
 658      *   u2 hashes_count;
 659      *   {   u2 module_name_index
 660      *       u2 hash_length;
 661      *       u1 hash[hash_length];
 662      *   } hashes[hashes_count];
 663      *
 664      * } </pre>
 665      */
 666     static class ModuleHashesAttribute extends Attribute {
 667         private final ModuleHashes hashes;
 668 
 669         ModuleHashesAttribute(ModuleHashes hashes) {
 670             super(MODULE_HASHES);
 671             this.hashes = hashes;
 672         }
 673 
 674         ModuleHashesAttribute() {
 675             this(null);
 676         }
 677 
 678         @Override
 679         protected Attribute read(ClassReader cr,
 680                                  int off,
 681                                  int len,
 682                                  char[] buf,
 683                                  int codeOff,
 684                                  Label[] labels)
 685         {
 686             String algorithm = cr.readUTF8(off, buf);
 687             off += 2;
 688 
 689             int hashes_count = cr.readUnsignedShort(off);
 690             off += 2;
 691 
 692             Map<String, byte[]> map = new HashMap<>();
 693             for (int i=0; i<hashes_count; i++) {
 694                 String mn = cr.readUTF8(off, buf).replace('/', '.');
 695                 off += 2;
 696 
 697                 int hash_length = cr.readUnsignedShort(off);
 698                 off += 2;
 699                 byte[] hash = new byte[hash_length];
 700                 for (int j=0; j<hash_length; j++) {
 701                     hash[j] = (byte) (0xff & cr.readByte(off+j));
 702                 }
 703                 off += hash_length;
 704 
 705                 map.put(mn, hash);
 706             }
 707 
 708             ModuleHashes hashes = new ModuleHashes(algorithm, map);
 709 
 710             return new ModuleHashesAttribute(hashes);
 711         }
 712 
 713         @Override
 714         protected ByteVector write(ClassWriter cw,
 715                                    byte[] code,
 716                                    int len,
 717                                    int maxStack,
 718                                    int maxLocals)
 719         {
 720             ByteVector attr = new ByteVector();
 721 
 722             int index = cw.newUTF8(hashes.algorithm());
 723             attr.putShort(index);
 724 
 725             Set<String> names = hashes.names();
 726             attr.putShort(names.size());
 727 
 728             for (String mn : names) {
 729                 byte[] hash = hashes.hashFor(mn);
 730                 assert hash != null;
 731                 attr.putShort(cw.newUTF8(mn.replace('.', '/')));
 732 
 733                 attr.putShort(hash.length);
 734                 for (byte b: hash) {
 735                     attr.putByte(b);
 736                 }
 737             }
 738 
 739             return attr;
 740         }
 741     }
 742 






















































 743 }


  51 
  52 /**
  53  * Provides ASM implementations of {@code Attribute} to read and write the
  54  * class file attributes in a module-info class file.
  55  */
  56 
  57 public final class ClassFileAttributes {
  58 
  59     private ClassFileAttributes() { }
  60 
  61     /**
  62      * Module_attribute {
  63      *   // See lang-vm.html for details.
  64      * }
  65      */
  66     public static class ModuleAttribute extends Attribute {
  67         private static final JavaLangModuleAccess JLMA
  68             = SharedSecrets.getJavaLangModuleAccess();
  69 
  70         private ModuleDescriptor descriptor;
  71         private Version replacementVersion;
  72 
  73         public ModuleAttribute(ModuleDescriptor descriptor) {
  74             super(MODULE);
  75             this.descriptor = descriptor;
  76         }
  77 
  78         public ModuleAttribute(Version v) {
  79             super(MODULE);
  80             this.replacementVersion = v;
  81         }
  82 
  83         public ModuleAttribute() {
  84             super(MODULE);
  85         }
  86 
  87         @Override
  88         protected Attribute read(ClassReader cr,
  89                                  int off,
  90                                  int len,
  91                                  char[] buf,
  92                                  int codeOff,
  93                                  Label[] labels)
  94         {
  95             // module_name (CONSTANT_Module_info)
  96             String mn = cr.readModule(off, buf);


  97             off += 2;
  98 
  99             // module_flags
 100             int module_flags = cr.readUnsignedShort(off);
 101             boolean open = ((module_flags & ACC_OPEN) != 0);
 102             boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0);
 103             off += 2;
 104 
 105             ModuleDescriptor.Builder builder = JLMA.newModuleBuilder(mn,
 106                                                                      false,
 107                                                                      open,
 108                                                                      synthetic);
 109 
 110             // module_version
 111             String module_version = cr.readUTF8(off, buf);
 112             off += 2;
 113             if (replacementVersion != null) {
 114                 builder.version(replacementVersion);
 115             } else if (module_version != null) {
 116                 builder.version(module_version);
 117             }
 118 
 119             // requires_count and requires[requires_count]
 120             int requires_count = cr.readUnsignedShort(off);
 121             off += 2;
 122             for (int i=0; i<requires_count; i++) {
 123                 // CONSTANT_Module_info
 124                 String dn = cr.readModule(off, buf);
 125                 off += 2;
 126 
 127                 // requires_flags
 128                 int requires_flags = cr.readUnsignedShort(off);
 129                 off += 2;
 130                 Set<Requires.Modifier> mods;
 131                 if (requires_flags == 0) {
 132                     mods = Collections.emptySet();
 133                 } else {
 134                     mods = new HashSet<>();
 135                     if ((requires_flags & ACC_TRANSITIVE) != 0)
 136                         mods.add(Requires.Modifier.TRANSITIVE);
 137                     if ((requires_flags & ACC_STATIC_PHASE) != 0)
 138                         mods.add(Requires.Modifier.STATIC);
 139                     if ((requires_flags & ACC_SYNTHETIC) != 0)
 140                         mods.add(Requires.Modifier.SYNTHETIC);
 141                     if ((requires_flags & ACC_MANDATED) != 0)
 142                         mods.add(Requires.Modifier.MANDATED);
 143                 }
 144 
 145 
 146                 // requires_version
 147                 Version compiledVersion = null;
 148                 String requires_version = cr.readUTF8(off, buf);
 149                 off += 2;
 150                 if (requires_version != null) {
 151                     compiledVersion = Version.parse(requires_version);
 152                 }
 153 
 154                 if (compiledVersion == null) {
 155                     builder.requires(mods, dn);
 156                 } else {
 157                     builder.requires(mods, dn, compiledVersion);
 158                 }
 159             }
 160 
 161             // exports_count and exports[exports_count]
 162             int exports_count = cr.readUnsignedShort(off);
 163             off += 2;
 164             if (exports_count > 0) {
 165                 for (int i=0; i<exports_count; i++) {
 166                     // CONSTANT_Package_info
 167                     String pkg = cr.readPackage(off, buf).replace('/', '.');
 168                     off += 2;
 169 
 170                     int exports_flags = cr.readUnsignedShort(off);
 171                     off += 2;
 172                     Set<Exports.Modifier> mods;
 173                     if (exports_flags == 0) {
 174                         mods = Collections.emptySet();
 175                     } else {
 176                         mods = new HashSet<>();
 177                         if ((exports_flags & ACC_SYNTHETIC) != 0)
 178                             mods.add(Exports.Modifier.SYNTHETIC);
 179                         if ((exports_flags & ACC_MANDATED) != 0)
 180                             mods.add(Exports.Modifier.MANDATED);
 181                     }
 182 
 183                     int exports_to_count = cr.readUnsignedShort(off);
 184                     off += 2;
 185                     if (exports_to_count > 0) {
 186                         Set<String> targets = new HashSet<>();
 187                         for (int j=0; j<exports_to_count; j++) {
 188                             String t = cr.readModule(off, buf);
 189                             off += 2;
 190                             targets.add(t);
 191                         }
 192                         builder.exports(mods, pkg, targets);
 193                     } else {
 194                         builder.exports(mods, pkg);
 195                     }
 196                 }
 197             }
 198 
 199             // opens_count and opens[opens_count]
 200             int open_count = cr.readUnsignedShort(off);
 201             off += 2;
 202             if (open_count > 0) {
 203                 for (int i=0; i<open_count; i++) {
 204                     // CONSTANT_Package_info
 205                     String pkg = cr.readPackage(off, buf).replace('/', '.');
 206                     off += 2;
 207 
 208                     int opens_flags = cr.readUnsignedShort(off);
 209                     off += 2;
 210                     Set<Opens.Modifier> mods;
 211                     if (opens_flags == 0) {
 212                         mods = Collections.emptySet();
 213                     } else {
 214                         mods = new HashSet<>();
 215                         if ((opens_flags & ACC_SYNTHETIC) != 0)
 216                             mods.add(Opens.Modifier.SYNTHETIC);
 217                         if ((opens_flags & ACC_MANDATED) != 0)
 218                             mods.add(Opens.Modifier.MANDATED);
 219                     }
 220 
 221                     int opens_to_count = cr.readUnsignedShort(off);
 222                     off += 2;
 223                     if (opens_to_count > 0) {
 224                         Set<String> targets = new HashSet<>();
 225                         for (int j=0; j<opens_to_count; j++) {
 226                             String t = cr.readModule(off, buf);
 227                             off += 2;
 228                             targets.add(t);
 229                         }
 230                         builder.opens(mods, pkg, targets);
 231                     } else {
 232                         builder.opens(mods, pkg);
 233                     }
 234                 }
 235             }
 236 
 237             // uses_count and uses_index[uses_count]
 238             int uses_count = cr.readUnsignedShort(off);
 239             off += 2;
 240             if (uses_count > 0) {
 241                 for (int i=0; i<uses_count; i++) {
 242                     String sn = cr.readClass(off, buf).replace('/', '.');
 243                     builder.uses(sn);
 244                     off += 2;
 245                 }
 246             }
 247 
 248             // provides_count and provides[provides_count]
 249             int provides_count = cr.readUnsignedShort(off);
 250             off += 2;
 251             if (provides_count > 0) {
 252                 for (int i=0; i<provides_count; i++) {
 253                     String service = cr.readClass(off, buf).replace('/', '.');
 254                     off += 2;
 255                     int with_count = cr.readUnsignedShort(off);
 256                     off += 2;
 257                     List<String> providers = new ArrayList<>();
 258                     for (int j=0; j<with_count; j++) {
 259                         String cn = cr.readClass(off, buf).replace('/', '.');
 260                         off += 2;
 261                         providers.add(cn);
 262                     }
 263                     builder.provides(service, providers);
 264                 }
 265             }
 266 
 267             return new ModuleAttribute(builder.build());

 268         }
 269 
 270         @Override
 271         protected ByteVector write(ClassWriter cw,
 272                                    byte[] code,
 273                                    int len,
 274                                    int maxStack,
 275                                    int maxLocals)
 276         {
 277             assert descriptor != null;
 278             ByteVector attr = new ByteVector();
 279 
 280             // module_name
 281             String mn = descriptor.name();
 282             int module_name_index = cw.newModule(mn);
 283             attr.putShort(module_name_index);
 284 
 285             // module_flags
 286             int module_flags = 0;
 287             if (descriptor.isOpen())
 288                 module_flags |= ACC_OPEN;
 289             if (descriptor.isSynthetic())
 290                 module_flags |= ACC_SYNTHETIC;
 291             attr.putShort(module_flags);
 292 
 293             // module_version
 294             Version v = descriptor.version().orElse(null);
 295             if (v == null) {
 296                 attr.putShort(0);
 297             } else {
 298                 int module_version_index = cw.newUTF8(v.toString());
 299                 attr.putShort(module_version_index);
 300             }
 301 
 302             // requires_count
 303             attr.putShort(descriptor.requires().size());
 304 
 305             // requires[requires_count]
 306             for (Requires r : descriptor.requires()) {
 307                 int requires_index = cw.newModule(r.name());
 308                 attr.putShort(requires_index);
 309 
 310                 int requires_flags = 0;
 311                 if (r.modifiers().contains(Requires.Modifier.TRANSITIVE))
 312                     requires_flags |= ACC_TRANSITIVE;
 313                 if (r.modifiers().contains(Requires.Modifier.STATIC))
 314                     requires_flags |= ACC_STATIC_PHASE;
 315                 if (r.modifiers().contains(Requires.Modifier.SYNTHETIC))
 316                     requires_flags |= ACC_SYNTHETIC;
 317                 if (r.modifiers().contains(Requires.Modifier.MANDATED))
 318                     requires_flags |= ACC_MANDATED;
 319                 attr.putShort(requires_flags);
 320 
 321                 int requires_version_index;
 322                 v = r.compiledVersion().orElse(null);
 323                 if (v == null) {
 324                     requires_version_index = 0;
 325                 } else {
 326                     requires_version_index = cw.newUTF8(v.toString());
 327                 }
 328                 attr.putShort(requires_version_index);
 329             }
 330 
 331             // exports_count and exports[exports_count];
 332             attr.putShort(descriptor.exports().size());
 333             for (Exports e : descriptor.exports()) {
 334                 String pkg = e.source().replace('.', '/');
 335                 attr.putShort(cw.newPackage(pkg));
 336 
 337                 int exports_flags = 0;
 338                 if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
 339                     exports_flags |= ACC_SYNTHETIC;
 340                 if (e.modifiers().contains(Exports.Modifier.MANDATED))
 341                     exports_flags |= ACC_MANDATED;
 342                 attr.putShort(exports_flags);
 343 
 344                 if (e.isQualified()) {
 345                     Set<String> ts = e.targets();
 346                     attr.putShort(ts.size());
 347                     ts.forEach(target -> attr.putShort(cw.newModule(target)));
 348                 } else {
 349                     attr.putShort(0);
 350                 }
 351             }
 352 

 353             // opens_counts and opens[opens_counts]
 354             attr.putShort(descriptor.opens().size());
 355             for (Opens obj : descriptor.opens()) {
 356                 String pkg = obj.source().replace('.', '/');
 357                 attr.putShort(cw.newPackage(pkg));
 358 
 359                 int opens_flags = 0;
 360                 if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
 361                     opens_flags |= ACC_SYNTHETIC;
 362                 if (obj.modifiers().contains(Opens.Modifier.MANDATED))
 363                     opens_flags |= ACC_MANDATED;
 364                 attr.putShort(opens_flags);
 365 
 366                 if (obj.isQualified()) {
 367                     Set<String> ts = obj.targets();
 368                     attr.putShort(ts.size());
 369                     ts.forEach(target -> attr.putShort(cw.newModule(target)));
 370                 } else {
 371                     attr.putShort(0);
 372                 }
 373             }
 374 
 375             // uses_count and uses_index[uses_count]
 376             if (descriptor.uses().isEmpty()) {
 377                 attr.putShort(0);
 378             } else {
 379                 attr.putShort(descriptor.uses().size());
 380                 for (String s : descriptor.uses()) {
 381                     String service = s.replace('.', '/');
 382                     int index = cw.newClass(service);
 383                     attr.putShort(index);
 384                 }
 385             }
 386 
 387             // provides_count and provides[provides_count]
 388             if (descriptor.provides().isEmpty()) {
 389                 attr.putShort(0);


 400                 }
 401             }
 402 
 403             return attr;
 404         }
 405     }
 406 
 407     /**
 408      * ModulePackages attribute.
 409      *
 410      * <pre> {@code
 411      *
 412      * ModulePackages_attribute {
 413      *   // index to CONSTANT_utf8_info structure in constant pool representing
 414      *   // the string "ModulePackages"
 415      *   u2 attribute_name_index;
 416      *   u4 attribute_length;
 417      *
 418      *   // the number of entries in the packages table
 419      *   u2 packages_count;
 420      *   { // index to CONSTANT_Package_info structure with the package name
 421      *     u2 package_index
 422      *   } packages[package_count];
 423      *
 424      * }</pre>
 425      */
 426     public static class ModulePackagesAttribute extends Attribute {
 427         private final Set<String> packages;
 428 
 429         public ModulePackagesAttribute(Set<String> packages) {
 430             super(MODULE_PACKAGES);
 431             this.packages = packages;
 432         }
 433 
 434         public ModulePackagesAttribute() {
 435             this(null);
 436         }
 437 
 438         @Override
 439         protected Attribute read(ClassReader cr,
 440                                  int off,
 441                                  int len,
 442                                  char[] buf,
 443                                  int codeOff,
 444                                  Label[] labels)
 445         {
 446             // package count
 447             int package_count = cr.readUnsignedShort(off);
 448             off += 2;
 449 
 450             // packages
 451             Set<String> packages = new HashSet<>();
 452             for (int i=0; i<package_count; i++) {
 453                 String pkg = cr.readPackage(off, buf).replace('/', '.');
 454                 packages.add(pkg);
 455                 off += 2;
 456             }
 457 
 458             return new ModulePackagesAttribute(packages);
 459         }
 460 
 461         @Override
 462         protected ByteVector write(ClassWriter cw,
 463                                    byte[] code,
 464                                    int len,
 465                                    int maxStack,
 466                                    int maxLocals)
 467         {
 468             assert packages != null;
 469 
 470             ByteVector attr = new ByteVector();
 471 
 472             // package_count
 473             attr.putShort(packages.size());
 474 
 475             // packages
 476             packages.stream()
 477                 .map(p -> p.replace('.', '/'))
 478                 .forEach(p -> attr.putShort(cw.newPackage(p)));
 479 
 480             return attr;
 481         }
 482 
 483     }
 484 
 485     /**























































 486      * ModuleMainClass attribute.
 487      *
 488      * <pre> {@code
 489      *
 490      * MainClass_attribute {
 491      *   // index to CONSTANT_utf8_info structure in constant pool representing
 492      *   // the string "ModuleMainClass"
 493      *   u2 attribute_name_index;
 494      *   u4 attribute_length;
 495      *
 496      *   // index to CONSTANT_Class_info structure with the main class name
 497      *   u2 main_class_index;
 498      * }
 499      *
 500      * } </pre>
 501      */
 502     public static class ModuleMainClassAttribute extends Attribute {
 503         private final String mainClass;
 504 
 505         public ModuleMainClassAttribute(String mainClass) {
 506             super(MODULE_MAIN_CLASS);
 507             this.mainClass = mainClass;
 508         }
 509 
 510         public ModuleMainClassAttribute() {
 511             this(null);
 512         }
 513 
 514         @Override
 515         protected Attribute read(ClassReader cr,
 516                                  int off,
 517                                  int len,
 518                                  char[] buf,
 519                                  int codeOff,
 520                                  Label[] labels)
 521         {
 522             String value = cr.readClass(off, buf).replace('/', '.');
 523             return new ModuleMainClassAttribute(value);
 524         }
 525 
 526         @Override
 527         protected ByteVector write(ClassWriter cw,
 528                                    byte[] code,
 529                                    int len,
 530                                    int maxStack,
 531                                    int maxLocals)
 532         {
 533             ByteVector attr = new ByteVector();
 534             int index = cw.newClass(mainClass.replace('.', '/'));
 535             attr.putShort(index);
 536             return attr;
 537         }
 538     }
 539 
 540     /**
 541      * ModuleTarget attribute.
 542      *
 543      * <pre> {@code
 544      *
 545      * TargetPlatform_attribute {
 546      *   // index to CONSTANT_utf8_info structure in constant pool representing
 547      *   // the string "ModuleTarget"
 548      *   u2 attribute_name_index;
 549      *   u4 attribute_length;
 550      *
 551      *   // index to CONSTANT_utf8_info structure with the OS name
 552      *   u2 os_name_index;
 553      *   // index to CONSTANT_utf8_info structure with the OS arch
 554      *   u2 os_arch_index
 555      *   // index to CONSTANT_utf8_info structure with the OS version
 556      *   u2 os_version_index;
 557      * }
 558      *
 559      * } </pre>
 560      */
 561     public static class ModuleTargetAttribute extends Attribute {
 562         private final String osName;
 563         private final String osArch;
 564         private final String osVersion;
 565 
 566         public ModuleTargetAttribute(String osName, String osArch, String osVersion) {
 567             super(MODULE_TARGET);
 568             this.osName = osName;
 569             this.osArch = osArch;
 570             this.osVersion = osVersion;
 571         }
 572 
 573         public ModuleTargetAttribute() {
 574             this(null, null, null);
 575         }


 632             return attr;
 633         }
 634     }
 635 
 636     /**
 637      * ModuleHashes attribute.
 638      *
 639      * <pre> {@code
 640      *
 641      * ModuleHashes_attribute {
 642      *   // index to CONSTANT_utf8_info structure in constant pool representing
 643      *   // the string "ModuleHashes"
 644      *   u2 attribute_name_index;
 645      *   u4 attribute_length;
 646      *
 647      *   // index to CONSTANT_utf8_info structure with algorithm name
 648      *   u2 algorithm_index;
 649      *
 650      *   // the number of entries in the hashes table
 651      *   u2 hashes_count;
 652      *   {   u2 module_name_index (index to CONSTANT_Module_info structure)
 653      *       u2 hash_length;
 654      *       u1 hash[hash_length];
 655      *   } hashes[hashes_count];
 656      *
 657      * } </pre>
 658      */
 659     static class ModuleHashesAttribute extends Attribute {
 660         private final ModuleHashes hashes;
 661 
 662         ModuleHashesAttribute(ModuleHashes hashes) {
 663             super(MODULE_HASHES);
 664             this.hashes = hashes;
 665         }
 666 
 667         ModuleHashesAttribute() {
 668             this(null);
 669         }
 670 
 671         @Override
 672         protected Attribute read(ClassReader cr,
 673                                  int off,
 674                                  int len,
 675                                  char[] buf,
 676                                  int codeOff,
 677                                  Label[] labels)
 678         {
 679             String algorithm = cr.readUTF8(off, buf);
 680             off += 2;
 681 
 682             int hashes_count = cr.readUnsignedShort(off);
 683             off += 2;
 684 
 685             Map<String, byte[]> map = new HashMap<>();
 686             for (int i=0; i<hashes_count; i++) {
 687                 String mn = cr.readModule(off, buf);
 688                 off += 2;
 689 
 690                 int hash_length = cr.readUnsignedShort(off);
 691                 off += 2;
 692                 byte[] hash = new byte[hash_length];
 693                 for (int j=0; j<hash_length; j++) {
 694                     hash[j] = (byte) (0xff & cr.readByte(off+j));
 695                 }
 696                 off += hash_length;
 697 
 698                 map.put(mn, hash);
 699             }
 700 
 701             ModuleHashes hashes = new ModuleHashes(algorithm, map);
 702 
 703             return new ModuleHashesAttribute(hashes);
 704         }
 705 
 706         @Override
 707         protected ByteVector write(ClassWriter cw,
 708                                    byte[] code,
 709                                    int len,
 710                                    int maxStack,
 711                                    int maxLocals)
 712         {
 713             ByteVector attr = new ByteVector();
 714 
 715             int index = cw.newUTF8(hashes.algorithm());
 716             attr.putShort(index);
 717 
 718             Set<String> names = hashes.names();
 719             attr.putShort(names.size());
 720 
 721             for (String mn : names) {
 722                 byte[] hash = hashes.hashFor(mn);
 723                 assert hash != null;
 724                 attr.putShort(cw.newModule(mn));
 725 
 726                 attr.putShort(hash.length);
 727                 for (byte b: hash) {
 728                     attr.putByte(b);
 729                 }
 730             }
 731 
 732             return attr;
 733         }
 734     }
 735 
 736     /**
 737      *  ModuleResolution_attribute {
 738      *    u2 attribute_name_index;    // "ModuleResolution"
 739      *    u4 attribute_length;        // 2
 740      *    u2 resolution_flags;
 741      *
 742      *  The value of the resolution_flags item is a mask of flags used to denote
 743      *  properties of module resolution. The flags are as follows:
 744      *
 745      *   // Optional
 746      *   0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
 747      *
 748      *   // At most one of:
 749      *   0x0002 (WARN_DEPRECATED)
 750      *   0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
 751      *   0x0008 (WARN_INCUBATING)
 752      */
 753     static class ModuleResolutionAttribute extends Attribute {
 754         private final int value;
 755 
 756         ModuleResolutionAttribute() {
 757             super(MODULE_RESOLUTION);
 758             value = 0;
 759         }
 760 
 761         ModuleResolutionAttribute(int value) {
 762             super(MODULE_RESOLUTION);
 763             this.value = value;
 764         }
 765 
 766         @Override
 767         protected Attribute read(ClassReader cr,
 768                                  int off,
 769                                  int len,
 770                                  char[] buf,
 771                                  int codeOff,
 772                                  Label[] labels)
 773         {
 774             int flags = cr.readUnsignedShort(off);
 775             return new ModuleResolutionAttribute(flags);
 776         }
 777 
 778         @Override
 779         protected ByteVector write(ClassWriter cw,
 780                                    byte[] code,
 781                                    int len,
 782                                    int maxStack,
 783                                    int maxLocals)
 784         {
 785             ByteVector attr = new ByteVector();
 786             attr.putShort(value);
 787             return attr;
 788         }
 789     }
 790 }
< prev index next >