< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java

Print this page

  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.jvm;
  27 
  28 import java.io.*;
  29 import java.util.LinkedHashMap;
  30 import java.util.Map;
  31 import java.util.Set;
  32 import java.util.LinkedHashSet;
  33 import java.util.function.ToIntFunction;
  34 
  35 import javax.tools.JavaFileManager;
  36 import javax.tools.FileObject;
  37 import javax.tools.JavaFileManager.Location;
  38 import javax.tools.JavaFileObject;
  39 
  40 import com.sun.tools.javac.code.*;
  41 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
  42 import com.sun.tools.javac.code.Directive.*;

  43 import com.sun.tools.javac.code.Source.Feature;
  44 import com.sun.tools.javac.code.Symbol.*;
  45 import com.sun.tools.javac.code.Type.*;
  46 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
  47 import com.sun.tools.javac.comp.Check;
  48 import com.sun.tools.javac.file.PathFileObject;
  49 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
  50 import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
  51 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  52 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  53 import com.sun.tools.javac.util.*;
  54 import com.sun.tools.javac.util.List;
  55 
  56 import static com.sun.tools.javac.code.Flags.*;
  57 import static com.sun.tools.javac.code.Kinds.Kind.*;
  58 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  59 import static com.sun.tools.javac.code.TypeTag.*;
  60 import static com.sun.tools.javac.main.Option.*;
  61 
  62 import static javax.tools.StandardLocation.CLASS_OUTPUT;

 125 
 126     /** An output buffer for member info.
 127      */
 128     public ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
 129 
 130     /** An output buffer for the constant pool.
 131      */
 132     ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
 133 
 134     /** The constant pool writer.
 135      */
 136     final PoolWriter poolWriter;
 137 
 138     /** The log to use for verbose output.
 139      */
 140     private final Log log;
 141 
 142     /** The name table. */
 143     private final Names names;
 144 


 145     /** Access to files. */
 146     private final JavaFileManager fileManager;
 147 
 148     /** The tags and constants used in compressed stackmap. */
 149     static final int SAME_FRAME_SIZE = 64;
 150     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
 151     static final int SAME_FRAME_EXTENDED = 251;
 152     static final int FULL_FRAME = 255;
 153     static final int MAX_LOCAL_LENGTH_DIFF = 4;
 154 
 155     /** Get the ClassWriter instance for this context. */
 156     public static ClassWriter instance(Context context) {
 157         ClassWriter instance = context.get(classWriterKey);
 158         if (instance == null)
 159             instance = new ClassWriter(context);
 160         return instance;
 161     }
 162 
 163     /** Construct a class writer, given an options table.
 164      */
 165     protected ClassWriter(Context context) {
 166         context.put(classWriterKey, this);
 167 
 168         log = Log.instance(context);
 169         names = Names.instance(context);
 170         options = Options.instance(context);
 171         preview = Preview.instance(context);
 172         target = Target.instance(context);
 173         source = Source.instance(context);
 174         types = Types.instance(context);
 175         check = Check.instance(context);
 176         fileManager = context.get(JavaFileManager.class);
 177         poolWriter = Gen.instance(context).poolWriter;

 178 
 179         verbose        = options.isSet(VERBOSE);
 180         genCrt         = options.isSet(XJCOV);
 181         debugstackmap = options.isSet("debug.stackmap");
 182 
 183         emitSourceFile = options.isUnset(G_CUSTOM) ||
 184                             options.isSet(G_CUSTOM, "source");
 185 
 186         String modifierFlags = options.get("debug.dumpmodifiers");
 187         if (modifierFlags != null) {
 188             dumpClassModifiers = modifierFlags.indexOf('c') != -1;
 189             dumpFieldModifiers = modifierFlags.indexOf('f') != -1;
 190             dumpInnerClassModifiers = modifierFlags.indexOf('i') != -1;
 191             dumpMethodModifiers = modifierFlags.indexOf('m') != -1;
 192         }
 193     }
 194 
 195     public void addExtraAttributes(ToIntFunction<Symbol> addExtraAttributes) {
 196         extraAttributeHooks = extraAttributeHooks.prepend(addExtraAttributes);
 197     }

 808             databuf.appendChar(poolWriter.putClass(srvc));
 809             databuf.appendChar(impls.size());
 810             impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
 811         });
 812 
 813         endAttr(alenIdx);
 814         return 1;
 815     }
 816 
 817 /**********************************************************************
 818  * Writing Objects
 819  **********************************************************************/
 820 
 821     /** Write "inner classes" attribute.
 822      */
 823     void writeInnerClasses() {
 824         int alenIdx = writeAttr(names.InnerClasses);
 825         databuf.appendChar(poolWriter.innerClasses.size());
 826         for (ClassSymbol inner : poolWriter.innerClasses) {
 827             inner.markAbstractIfNeeded(types);
 828             char flags = (char) adjustFlags(inner.flags_field);
 829             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
 830             flags &= ~STRICTFP; //inner classes should not have the strictfp flag set.
 831             if (dumpInnerClassModifiers) {
 832                 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 833                 pw.println("INNERCLASS  " + inner.name);
 834                 pw.println("---" + flagNames(flags));
 835             }
 836             databuf.appendChar(poolWriter.putClass(inner));
 837             databuf.appendChar(
 838                 inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
 839             databuf.appendChar(
 840                 !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
 841             databuf.appendChar(flags);
 842         }
 843         endAttr(alenIdx);
 844     }
 845 











 846     int writeRecordAttribute(ClassSymbol csym) {
 847         int alenIdx = writeAttr(names.Record);
 848         Scope s = csym.members();
 849         databuf.appendChar(csym.getRecordComponents().size());
 850         for (VarSymbol v: csym.getRecordComponents()) {
 851             //databuf.appendChar(poolWriter.putMember(v.accessor.head.snd));
 852             databuf.appendChar(poolWriter.putName(v.name));
 853             databuf.appendChar(poolWriter.putDescriptor(v));
 854             int acountIdx = beginAttrs();
 855             int acount = 0;
 856             acount += writeMemberAttrs(v, true);
 857             endAttrs(acountIdx, acount);
 858         }
 859         endAttr(alenIdx);
 860         return 1;
 861     }
 862 
 863     /**
 864      * Write NestMembers attribute (if needed)
 865      */

 988             writeCode(m.code);
 989             m.code = null; // to conserve space
 990             endAttr(alenIdx);
 991             acount++;
 992         }
 993         List<Type> thrown = m.erasure(types).getThrownTypes();
 994         if (thrown.nonEmpty()) {
 995             int alenIdx = writeAttr(names.Exceptions);
 996             databuf.appendChar(thrown.length());
 997             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
 998                 databuf.appendChar(poolWriter.putClass(l.head));
 999             endAttr(alenIdx);
1000             acount++;
1001         }
1002         if (m.defaultValue != null) {
1003             int alenIdx = writeAttr(names.AnnotationDefault);
1004             m.defaultValue.accept(awriter);
1005             endAttr(alenIdx);
1006             acount++;
1007         }
1008         if (target.hasMethodParameters() && (options.isSet(PARAMETERS) || m.isConstructor() && (m.flags_field & RECORD) != 0)) {


1009             if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies.
1010                 acount += writeMethodParametersAttr(m);
1011         }
1012         acount += writeMemberAttrs(m, false);
1013         if (!m.isLambdaMethod())
1014             acount += writeParameterAttrs(m.params);
1015         acount += writeExtraAttributes(m);
1016         endAttrs(acountIdx, acount);
1017     }
1018 
1019     /** Write code attribute of method.
1020      */
1021     void writeCode(Code code) {
1022         databuf.appendChar(code.max_stack);
1023         databuf.appendChar(code.max_locals);
1024         databuf.appendInt(code.cp);
1025         databuf.appendBytes(code.code, 0, code.cp);
1026         databuf.appendChar(code.catchInfo.length());
1027         for (List<char[]> l = code.catchInfo.toList();
1028              l.nonEmpty();

1208                 databuf.appendByte(1);
1209                 break;
1210             case FLOAT:
1211                 if (debugstackmap) System.out.print("float");
1212                 databuf.appendByte(2);
1213                 break;
1214             case DOUBLE:
1215                 if (debugstackmap) System.out.print("double");
1216                 databuf.appendByte(3);
1217                 break;
1218             case LONG:
1219                 if (debugstackmap) System.out.print("long");
1220                 databuf.appendByte(4);
1221                 break;
1222             case BOT: // null
1223                 if (debugstackmap) System.out.print("null");
1224                 databuf.appendByte(5);
1225                 break;
1226             case CLASS:
1227             case ARRAY:




1228             case TYPEVAR:
1229                 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1230                 databuf.appendByte(7);
1231                 databuf.appendChar(poolWriter.putClass(types.erasure(t)));
1232                 break;
1233             case UNINITIALIZED_THIS:
1234                 if (debugstackmap) System.out.print("uninit_this");
1235                 databuf.appendByte(6);
1236                 break;
1237             case UNINITIALIZED_OBJECT:
1238                 { UninitializedType uninitType = (UninitializedType)t;
1239                 databuf.appendByte(8);
1240                 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1241                 databuf.appendChar(uninitType.offset);
1242                 }
1243                 break;
1244             default:
1245                 throw new AssertionError();
1246             }
1247         }

1519         }
1520         return outFile; // may be null if write failed
1521     }
1522 
1523     /** Write class `c' to outstream `out'.
1524      */
1525     public void writeClassFile(OutputStream out, ClassSymbol c)
1526         throws IOException, PoolOverflow, StringOverflow {
1527         Assert.check((c.flags() & COMPOUND) == 0);
1528         databuf.reset();
1529         poolbuf.reset();
1530 
1531         Type supertype = types.supertype(c.type);
1532         List<Type> interfaces = types.interfaces(c.type);
1533         List<Type> typarams = c.type.getTypeArguments();
1534 
1535         int flags;
1536         if (c.owner.kind == MDL) {
1537             flags = ACC_MODULE;
1538         } else {
1539             flags = adjustFlags(c.flags() & ~DEFAULT);
1540             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1541             flags = flags & ClassFlags & ~STRICTFP;
1542             if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
1543         }
1544 
1545         if (dumpClassModifiers) {
1546             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1547             pw.println();
1548             pw.println("CLASSFILE  " + c.getQualifiedName());
1549             pw.println("---" + flagNames(flags));
1550         }
1551         databuf.appendChar(flags);
1552 
1553         if (c.owner.kind == MDL) {
1554             PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1555             databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
1556         } else {
1557             databuf.appendChar(poolWriter.putClass(c));
1558         }
1559         databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
1560         databuf.appendChar(interfaces.length());
1561         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1562             databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
1563         int fieldsCount = 0;
1564         int methodsCount = 0;
1565         for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
1566             switch (sym.kind) {
1567             case VAR: fieldsCount++; break;
1568             case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
1569                       break;
1570             case TYP: poolWriter.enterInner((ClassSymbol)sym); break;
1571             default : Assert.error();
1572             }
1573         }
1574 
1575         if (c.trans_local != null) {
1576             for (ClassSymbol local : c.trans_local) {
1577                 poolWriter.enterInner(local);
1578             }
1579         }
1580 
1581         databuf.appendChar(fieldsCount);
1582         writeFields(c.members());
1583         databuf.appendChar(methodsCount);
1584         writeMethods(c.members());
1585 
1586         int acountIdx = beginAttrs();
1587         int acount = 0;
1588 
1589         boolean sigReq =
1590             typarams.length() != 0 || supertype.allparams().length() != 0;
1591         for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
1592             sigReq = l.head.allparams().length() != 0;
1593         if (sigReq) {
1594             int alenIdx = writeAttr(names.Signature);
1595             databuf.appendChar(poolWriter.putSignature(c));
1596             endAttr(alenIdx);
1597             acount++;

1648         }
1649 
1650         if (c.isRecord()) {
1651             acount += writeRecordAttribute(c);
1652         }
1653 
1654         if (target.hasSealedClasses()) {
1655             acount += writePermittedSubclassesIfNeeded(c);
1656         }
1657 
1658         if (!poolWriter.bootstrapMethods.isEmpty()) {
1659             writeBootstrapMethods();
1660             acount++;
1661         }
1662 
1663         if (!poolWriter.innerClasses.isEmpty()) {
1664             writeInnerClasses();
1665             acount++;
1666         }
1667 





1668         endAttrs(acountIdx, acount);
1669 
1670         out.write(poolbuf.elems, 0, poolbuf.length);
1671 
1672         poolWriter.writePool(out);
1673         poolWriter.reset(); // to save space
1674 
1675         out.write(databuf.elems, 0, databuf.length);
1676     }
1677 
1678      /**Allows subclasses to write additional class attributes
1679       *
1680       * @return the number of attributes written
1681       */
1682     protected int writeExtraClassAttributes(ClassSymbol c) {
1683         return 0;
1684     }
1685 
1686     /**Allows friends to write additional attributes
1687      *

1691         int i = 0;
1692         for (ToIntFunction<Symbol> hook : extraAttributeHooks) {
1693             i += hook.applyAsInt(sym);
1694         }
1695         return i;
1696     }
1697 
1698     int adjustFlags(final long flags) {
1699         int result = (int)flags;
1700 
1701         // Elide strictfp bit in class files
1702         if (target.obsoleteAccStrict())
1703             result &= ~STRICTFP;
1704 
1705         if ((flags & BRIDGE) != 0)
1706             result |= ACC_BRIDGE;
1707         if ((flags & VARARGS) != 0)
1708             result |= ACC_VARARGS;
1709         if ((flags & DEFAULT) != 0)
1710             result &= ~ABSTRACT;




1711         return result;
1712     }
1713 
1714     long getLastModified(FileObject filename) {
1715         long mod = 0;
1716         try {
1717             mod = filename.getLastModified();
1718         } catch (SecurityException e) {
1719             throw new AssertionError("CRT: couldn't get source file modification date: " + e.getMessage());
1720         }
1721         return mod;
1722     }
1723 }

  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.jvm;
  27 
  28 import java.io.*;
  29 import java.util.LinkedHashMap;
  30 import java.util.Map;
  31 import java.util.Set;
  32 import java.util.LinkedHashSet;
  33 import java.util.function.ToIntFunction;
  34 
  35 import javax.tools.JavaFileManager;
  36 import javax.tools.FileObject;
  37 import javax.tools.JavaFileManager.Location;
  38 import javax.tools.JavaFileObject;
  39 
  40 import com.sun.tools.javac.code.*;
  41 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
  42 import com.sun.tools.javac.code.Directive.*;
  43 import com.sun.tools.javac.code.Scope.WriteableScope;
  44 import com.sun.tools.javac.code.Source.Feature;
  45 import com.sun.tools.javac.code.Symbol.*;
  46 import com.sun.tools.javac.code.Type.*;
  47 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
  48 import com.sun.tools.javac.comp.Check;
  49 import com.sun.tools.javac.file.PathFileObject;
  50 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
  51 import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
  52 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  53 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  54 import com.sun.tools.javac.util.*;
  55 import com.sun.tools.javac.util.List;
  56 
  57 import static com.sun.tools.javac.code.Flags.*;
  58 import static com.sun.tools.javac.code.Kinds.Kind.*;
  59 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  60 import static com.sun.tools.javac.code.TypeTag.*;
  61 import static com.sun.tools.javac.main.Option.*;
  62 
  63 import static javax.tools.StandardLocation.CLASS_OUTPUT;

 126 
 127     /** An output buffer for member info.
 128      */
 129     public ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE);
 130 
 131     /** An output buffer for the constant pool.
 132      */
 133     ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
 134 
 135     /** The constant pool writer.
 136      */
 137     final PoolWriter poolWriter;
 138 
 139     /** The log to use for verbose output.
 140      */
 141     private final Log log;
 142 
 143     /** The name table. */
 144     private final Names names;
 145 
 146     private final Symtab syms;
 147 
 148     /** Access to files. */
 149     private final JavaFileManager fileManager;
 150 
 151     /** The tags and constants used in compressed stackmap. */
 152     static final int SAME_FRAME_SIZE = 64;
 153     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
 154     static final int SAME_FRAME_EXTENDED = 251;
 155     static final int FULL_FRAME = 255;
 156     static final int MAX_LOCAL_LENGTH_DIFF = 4;
 157 
 158     /** Get the ClassWriter instance for this context. */
 159     public static ClassWriter instance(Context context) {
 160         ClassWriter instance = context.get(classWriterKey);
 161         if (instance == null)
 162             instance = new ClassWriter(context);
 163         return instance;
 164     }
 165 
 166     /** Construct a class writer, given an options table.
 167      */
 168     protected ClassWriter(Context context) {
 169         context.put(classWriterKey, this);
 170 
 171         log = Log.instance(context);
 172         names = Names.instance(context);
 173         options = Options.instance(context);
 174         preview = Preview.instance(context);
 175         target = Target.instance(context);
 176         source = Source.instance(context);
 177         types = Types.instance(context);
 178         check = Check.instance(context);
 179         fileManager = context.get(JavaFileManager.class);
 180         poolWriter = Gen.instance(context).poolWriter;
 181         syms = Symtab.instance(context);
 182 
 183         verbose        = options.isSet(VERBOSE);
 184         genCrt         = options.isSet(XJCOV);
 185         debugstackmap = options.isSet("debug.stackmap");
 186 
 187         emitSourceFile = options.isUnset(G_CUSTOM) ||
 188                             options.isSet(G_CUSTOM, "source");
 189 
 190         String modifierFlags = options.get("debug.dumpmodifiers");
 191         if (modifierFlags != null) {
 192             dumpClassModifiers = modifierFlags.indexOf('c') != -1;
 193             dumpFieldModifiers = modifierFlags.indexOf('f') != -1;
 194             dumpInnerClassModifiers = modifierFlags.indexOf('i') != -1;
 195             dumpMethodModifiers = modifierFlags.indexOf('m') != -1;
 196         }
 197     }
 198 
 199     public void addExtraAttributes(ToIntFunction<Symbol> addExtraAttributes) {
 200         extraAttributeHooks = extraAttributeHooks.prepend(addExtraAttributes);
 201     }

 812             databuf.appendChar(poolWriter.putClass(srvc));
 813             databuf.appendChar(impls.size());
 814             impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
 815         });
 816 
 817         endAttr(alenIdx);
 818         return 1;
 819     }
 820 
 821 /**********************************************************************
 822  * Writing Objects
 823  **********************************************************************/
 824 
 825     /** Write "inner classes" attribute.
 826      */
 827     void writeInnerClasses() {
 828         int alenIdx = writeAttr(names.InnerClasses);
 829         databuf.appendChar(poolWriter.innerClasses.size());
 830         for (ClassSymbol inner : poolWriter.innerClasses) {
 831             inner.markAbstractIfNeeded(types);
 832             char flags = (char) adjustFlags(inner.flags_field & ~STRICTFP); // inner classes should not have the strictfp flag set.
 833             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT

 834             if (dumpInnerClassModifiers) {
 835                 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
 836                 pw.println("INNERCLASS  " + inner.name);
 837                 pw.println("---" + flagNames(flags));
 838             }
 839             databuf.appendChar(poolWriter.putClass(inner));
 840             databuf.appendChar(
 841                 inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
 842             databuf.appendChar(
 843                 !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
 844             databuf.appendChar(flags);
 845         }
 846         endAttr(alenIdx);
 847     }
 848 
 849      /** Write out "Preload" attribute by enumerating the value classes encountered during this compilation.
 850       */
 851      void writeValueClasses() {
 852         int alenIdx = writeAttr(names.Preload);
 853         databuf.appendChar(poolWriter.valueClasses.size());
 854         for (ClassSymbol c : poolWriter.valueClasses) {
 855             databuf.appendChar(poolWriter.putClass(c));
 856         }
 857         endAttr(alenIdx);
 858      }
 859 
 860     int writeRecordAttribute(ClassSymbol csym) {
 861         int alenIdx = writeAttr(names.Record);
 862         Scope s = csym.members();
 863         databuf.appendChar(csym.getRecordComponents().size());
 864         for (VarSymbol v: csym.getRecordComponents()) {
 865             //databuf.appendChar(poolWriter.putMember(v.accessor.head.snd));
 866             databuf.appendChar(poolWriter.putName(v.name));
 867             databuf.appendChar(poolWriter.putDescriptor(v));
 868             int acountIdx = beginAttrs();
 869             int acount = 0;
 870             acount += writeMemberAttrs(v, true);
 871             endAttrs(acountIdx, acount);
 872         }
 873         endAttr(alenIdx);
 874         return 1;
 875     }
 876 
 877     /**
 878      * Write NestMembers attribute (if needed)
 879      */

1002             writeCode(m.code);
1003             m.code = null; // to conserve space
1004             endAttr(alenIdx);
1005             acount++;
1006         }
1007         List<Type> thrown = m.erasure(types).getThrownTypes();
1008         if (thrown.nonEmpty()) {
1009             int alenIdx = writeAttr(names.Exceptions);
1010             databuf.appendChar(thrown.length());
1011             for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1012                 databuf.appendChar(poolWriter.putClass(l.head));
1013             endAttr(alenIdx);
1014             acount++;
1015         }
1016         if (m.defaultValue != null) {
1017             int alenIdx = writeAttr(names.AnnotationDefault);
1018             m.defaultValue.accept(awriter);
1019             endAttr(alenIdx);
1020             acount++;
1021         }
1022         if (target.hasMethodParameters() && (
1023                 options.isSet(PARAMETERS)
1024                 || ((m.flags_field & RECORD) != 0 && (m.isConstructor() || m.isValueObjectFactory())))) {
1025             if (!m.isLambdaMethod()) // Per JDK-8138729, do not emit parameters table for lambda bodies.
1026                 acount += writeMethodParametersAttr(m);
1027         }
1028         acount += writeMemberAttrs(m, false);
1029         if (!m.isLambdaMethod())
1030             acount += writeParameterAttrs(m.params);
1031         acount += writeExtraAttributes(m);
1032         endAttrs(acountIdx, acount);
1033     }
1034 
1035     /** Write code attribute of method.
1036      */
1037     void writeCode(Code code) {
1038         databuf.appendChar(code.max_stack);
1039         databuf.appendChar(code.max_locals);
1040         databuf.appendInt(code.cp);
1041         databuf.appendBytes(code.code, 0, code.cp);
1042         databuf.appendChar(code.catchInfo.length());
1043         for (List<char[]> l = code.catchInfo.toList();
1044              l.nonEmpty();

1224                 databuf.appendByte(1);
1225                 break;
1226             case FLOAT:
1227                 if (debugstackmap) System.out.print("float");
1228                 databuf.appendByte(2);
1229                 break;
1230             case DOUBLE:
1231                 if (debugstackmap) System.out.print("double");
1232                 databuf.appendByte(3);
1233                 break;
1234             case LONG:
1235                 if (debugstackmap) System.out.print("long");
1236                 databuf.appendByte(4);
1237                 break;
1238             case BOT: // null
1239                 if (debugstackmap) System.out.print("null");
1240                 databuf.appendByte(5);
1241                 break;
1242             case CLASS:
1243             case ARRAY:
1244                 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1245                 databuf.appendByte(7);
1246                 databuf.appendChar(types.isPrimitiveClass(t) ? poolWriter.putClass(new ConstantPoolQType(types.erasure(t), types)) : poolWriter.putClass(types.erasure(t)));
1247                 break;
1248             case TYPEVAR:
1249                 if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
1250                 databuf.appendByte(7);
1251                 databuf.appendChar(poolWriter.putClass(types.erasure(t)));
1252                 break;
1253             case UNINITIALIZED_THIS:
1254                 if (debugstackmap) System.out.print("uninit_this");
1255                 databuf.appendByte(6);
1256                 break;
1257             case UNINITIALIZED_OBJECT:
1258                 { UninitializedType uninitType = (UninitializedType)t;
1259                 databuf.appendByte(8);
1260                 if (debugstackmap) System.out.print("uninit_object@" + uninitType.offset);
1261                 databuf.appendChar(uninitType.offset);
1262                 }
1263                 break;
1264             default:
1265                 throw new AssertionError();
1266             }
1267         }

1539         }
1540         return outFile; // may be null if write failed
1541     }
1542 
1543     /** Write class `c' to outstream `out'.
1544      */
1545     public void writeClassFile(OutputStream out, ClassSymbol c)
1546         throws IOException, PoolOverflow, StringOverflow {
1547         Assert.check((c.flags() & COMPOUND) == 0);
1548         databuf.reset();
1549         poolbuf.reset();
1550 
1551         Type supertype = types.supertype(c.type);
1552         List<Type> interfaces = types.interfaces(c.type);
1553         List<Type> typarams = c.type.getTypeArguments();
1554 
1555         int flags;
1556         if (c.owner.kind == MDL) {
1557             flags = ACC_MODULE;
1558         } else {
1559             flags = adjustFlags(c.flags() & ~(DEFAULT | STRICTFP));
1560             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
1561             flags = flags & ClassFlags;
1562             if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
1563         }
1564 
1565         if (dumpClassModifiers) {
1566             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
1567             pw.println();
1568             pw.println("CLASSFILE  " + c.getQualifiedName());
1569             pw.println("---" + flagNames(flags));
1570         }
1571         databuf.appendChar(flags);
1572 
1573         if (c.owner.kind == MDL) {
1574             PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
1575             databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
1576         } else {
1577             databuf.appendChar(poolWriter.putClass(c));
1578         }
1579         databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
1580         databuf.appendChar(interfaces.length());
1581         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
1582             databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
1583         int fieldsCount = 0;
1584         int methodsCount = 0;
1585         for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
1586             switch (sym.kind) {
1587             case VAR: fieldsCount++; break;
1588             case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
1589                       break;
1590             case TYP: poolWriter.enterInnerAndValueClass((ClassSymbol)sym); break;
1591             default : Assert.error();
1592             }
1593         }
1594 
1595         if (c.trans_local != null) {
1596             for (ClassSymbol local : c.trans_local) {
1597                 poolWriter.enterInnerAndValueClass(local);
1598             }
1599         }
1600 
1601         databuf.appendChar(fieldsCount);
1602         writeFields(c.members());
1603         databuf.appendChar(methodsCount);
1604         writeMethods(c.members());
1605 
1606         int acountIdx = beginAttrs();
1607         int acount = 0;
1608 
1609         boolean sigReq =
1610             typarams.length() != 0 || supertype.allparams().length() != 0;
1611         for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
1612             sigReq = l.head.allparams().length() != 0;
1613         if (sigReq) {
1614             int alenIdx = writeAttr(names.Signature);
1615             databuf.appendChar(poolWriter.putSignature(c));
1616             endAttr(alenIdx);
1617             acount++;

1668         }
1669 
1670         if (c.isRecord()) {
1671             acount += writeRecordAttribute(c);
1672         }
1673 
1674         if (target.hasSealedClasses()) {
1675             acount += writePermittedSubclassesIfNeeded(c);
1676         }
1677 
1678         if (!poolWriter.bootstrapMethods.isEmpty()) {
1679             writeBootstrapMethods();
1680             acount++;
1681         }
1682 
1683         if (!poolWriter.innerClasses.isEmpty()) {
1684             writeInnerClasses();
1685             acount++;
1686         }
1687 
1688         if (!poolWriter.valueClasses.isEmpty()) {
1689             writeValueClasses();
1690             acount++;
1691         }
1692 
1693         endAttrs(acountIdx, acount);
1694 
1695         out.write(poolbuf.elems, 0, poolbuf.length);
1696 
1697         poolWriter.writePool(out);
1698         poolWriter.reset(); // to save space
1699 
1700         out.write(databuf.elems, 0, databuf.length);
1701     }
1702 
1703      /**Allows subclasses to write additional class attributes
1704       *
1705       * @return the number of attributes written
1706       */
1707     protected int writeExtraClassAttributes(ClassSymbol c) {
1708         return 0;
1709     }
1710 
1711     /**Allows friends to write additional attributes
1712      *

1716         int i = 0;
1717         for (ToIntFunction<Symbol> hook : extraAttributeHooks) {
1718             i += hook.applyAsInt(sym);
1719         }
1720         return i;
1721     }
1722 
1723     int adjustFlags(final long flags) {
1724         int result = (int)flags;
1725 
1726         // Elide strictfp bit in class files
1727         if (target.obsoleteAccStrict())
1728             result &= ~STRICTFP;
1729 
1730         if ((flags & BRIDGE) != 0)
1731             result |= ACC_BRIDGE;
1732         if ((flags & VARARGS) != 0)
1733             result |= ACC_VARARGS;
1734         if ((flags & DEFAULT) != 0)
1735             result &= ~ABSTRACT;
1736         if ((flags & PRIMITIVE_CLASS) != 0)
1737             result |= ACC_PRIMITIVE;
1738         if ((flags & VALUE_CLASS) != 0)
1739             result |= ACC_VALUE;
1740         return result;
1741     }
1742 
1743     long getLastModified(FileObject filename) {
1744         long mod = 0;
1745         try {
1746             mod = filename.getLastModified();
1747         } catch (SecurityException e) {
1748             throw new AssertionError("CRT: couldn't get source file modification date: " + e.getMessage());
1749         }
1750         return mod;
1751     }
1752 }
< prev index next >