< prev index next >

src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java

Print this page

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package com.sun.tools.javap;
 27 


 28 import java.lang.classfile.AccessFlags;
 29 import java.lang.classfile.Attributes;
 30 import java.lang.classfile.ClassFile;
 31 import java.lang.classfile.ClassHierarchyResolver;
 32 import java.lang.classfile.ClassModel;
 33 import java.lang.classfile.ClassSignature;
 34 import java.lang.classfile.FieldModel;
 35 import java.lang.classfile.MethodModel;
 36 import java.lang.classfile.MethodSignature;
 37 import java.lang.classfile.Signature;
 38 import java.lang.classfile.attribute.CodeAttribute;
 39 import java.lang.classfile.attribute.SignatureAttribute;
 40 import java.lang.classfile.constantpool.ClassEntry;
 41 import java.lang.classfile.constantpool.ConstantValueEntry;
 42 import java.lang.classfile.constantpool.PoolEntry;
 43 import java.lang.constant.ClassDesc;
 44 import java.lang.reflect.AccessFlag;
 45 import java.lang.reflect.ClassFileFormatVersion;
 46 import java.lang.reflect.Modifier;
 47 import java.net.URI;

105     }
106 
107     protected void setClassFile(ClassModel cm) {
108         classModel = cm;
109     }
110 
111     protected MethodModel getMethod() {
112         return method;
113     }
114 
115     protected void setMethod(MethodModel m) {
116         method = m;
117     }
118 
119     protected ClassFileFormatVersion cffv() {
120         var major = classModel.majorVersion();
121         if (major < JAVA_1_VERSION || major > ClassFile.latestMajorVersion())
122             // something not representable by CFFV, let's fall back
123             return ClassFileFormatVersion.latest();
124         if (major >= JAVA_12_VERSION && classModel.minorVersion() != 0) {
125             // preview versions aren't explicitly supported, but latest is good enough for now
126             return ClassFileFormatVersion.latest();
127         }
128         return ClassFileFormatVersion.fromMajor(major);
129     }
130 
131     public boolean write(ClassModel cm) {
132         errorReported = false;
133         setClassFile(cm);
134 
135         if (options.sysInfo || options.verbose) {
136             if (uri != null) {
137                 if (uri.getScheme().equals("file"))
138                     println("Classfile " + uri.getPath());
139                 else
140                     println("Classfile " + uri);
141             }
142             indent(+1);
143             if (lastModified != -1) {
144                 Date lm = new Date(lastModified);
145                 DateFormat df = DateFormat.getDateInstance();
146                 if (size > 0) {

150                     println("Last modified " + df.format(lm));
151                 }
152             } else if (size > 0) {
153                 println("Size " + size + " bytes");
154             }
155             if (digestName != null && digest != null) {
156                 StringBuilder sb = new StringBuilder();
157                 for (byte b: digest)
158                     sb.append(String.format("%02x", b));
159                 println(digestName + " checksum " + sb);
160             }
161         }
162 
163         cm.findAttribute(Attributes.sourceFile()).ifPresent(sfa ->
164             println("Compiled from \"" + sfa.sourceFile().stringValue() + "\""));
165 
166         if (options.sysInfo || options.verbose) {
167             indent(-1);
168         }
169 
170         writeModifiers(getClassModifiers(cm.flags()));
171 
172         if ((classModel.flags().flagsMask() & ACC_MODULE) != 0) {
173             var attr = classModel.findAttribute(Attributes.module());
174             if (attr.isPresent()) {
175                 var modAttr = attr.get();
176                 if ((modAttr.moduleFlagsMask() & ACC_OPEN) != 0) {
177                     print("open ");
178                 }
179                 print("module ");
180                 print(() -> modAttr.moduleName().name().stringValue());
181                 if (modAttr.moduleVersion().isPresent()) {
182                     print("@");
183                     print(() -> modAttr.moduleVersion().get().stringValue());
184                 }
185             } else {
186                 // fallback for malformed class files
187                 print("class ");
188                 print(() -> getJavaName(classModel.thisClass().asInternalName()));
189             }
190         } else {

793             case '\r': return "\\r";
794             case '\\': return "\\\\";
795             case '\'': return "\\'";
796             case '\"': return "\\\"";
797             default:   return String.format("\\u%04x", (int) c);
798         }
799     }
800 
801     private Set<String> getClassModifiers(AccessFlags flags) {
802         var flagSet = flagsReportUnknown(flags, cffv());
803         Set<AccessFlag> set;
804         if (flagSet.contains(AccessFlag.INTERFACE)) {
805             set = EnumSet.copyOf(flagSet);
806             set.remove(AccessFlag.ABSTRACT);
807         } else {
808             set = flagSet;
809         }
810         return getModifiers(set);
811     }
812 
















813     private static Set<String> getModifiers(Set<AccessFlag> flags) {
814         Set<String> s = new LinkedHashSet<>();
815         for (var f : flags)
816             if (f.sourceModifier()) s.add(f == AccessFlag.STRICT ? "strictfp" : f.name().toLowerCase(Locale.ROOT));
817         return s;
818     }
819 
820     private Set<String> getClassFlags(AccessFlags flags) {
821         return getFlags(flags.flagsMask(), flagsReportUnknown(flags, cffv()));
822     }
823 
824     private static Set<String> getFlags(int mask, Set<AccessFlag> flags) {
825         Set<String> s = new LinkedHashSet<>();
826         for (var f: flags) {
827             s.add("ACC_" + f.name());
828             mask = mask & ~f.mask();
829         }
830         while (mask != 0) {
831             int bit = Integer.highestOneBit(mask);
832             s.add("0x" + Integer.toHexString(bit));

  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package com.sun.tools.javap;
 27 
 28 import com.sun.tools.javac.code.Source;
 29 
 30 import java.lang.classfile.AccessFlags;
 31 import java.lang.classfile.Attributes;
 32 import java.lang.classfile.ClassFile;
 33 import java.lang.classfile.ClassHierarchyResolver;
 34 import java.lang.classfile.ClassModel;
 35 import java.lang.classfile.ClassSignature;
 36 import java.lang.classfile.FieldModel;
 37 import java.lang.classfile.MethodModel;
 38 import java.lang.classfile.MethodSignature;
 39 import java.lang.classfile.Signature;
 40 import java.lang.classfile.attribute.CodeAttribute;
 41 import java.lang.classfile.attribute.SignatureAttribute;
 42 import java.lang.classfile.constantpool.ClassEntry;
 43 import java.lang.classfile.constantpool.ConstantValueEntry;
 44 import java.lang.classfile.constantpool.PoolEntry;
 45 import java.lang.constant.ClassDesc;
 46 import java.lang.reflect.AccessFlag;
 47 import java.lang.reflect.ClassFileFormatVersion;
 48 import java.lang.reflect.Modifier;
 49 import java.net.URI;

107     }
108 
109     protected void setClassFile(ClassModel cm) {
110         classModel = cm;
111     }
112 
113     protected MethodModel getMethod() {
114         return method;
115     }
116 
117     protected void setMethod(MethodModel m) {
118         method = m;
119     }
120 
121     protected ClassFileFormatVersion cffv() {
122         var major = classModel.majorVersion();
123         if (major < JAVA_1_VERSION || major > ClassFile.latestMajorVersion())
124             // something not representable by CFFV, let's fall back
125             return ClassFileFormatVersion.latest();
126         if (major >= JAVA_12_VERSION && classModel.minorVersion() != 0) {
127             return null;

128         }
129         return ClassFileFormatVersion.fromMajor(major);
130     }
131 
132     public boolean write(ClassModel cm) {
133         errorReported = false;
134         setClassFile(cm);
135 
136         if (options.sysInfo || options.verbose) {
137             if (uri != null) {
138                 if (uri.getScheme().equals("file"))
139                     println("Classfile " + uri.getPath());
140                 else
141                     println("Classfile " + uri);
142             }
143             indent(+1);
144             if (lastModified != -1) {
145                 Date lm = new Date(lastModified);
146                 DateFormat df = DateFormat.getDateInstance();
147                 if (size > 0) {

151                     println("Last modified " + df.format(lm));
152                 }
153             } else if (size > 0) {
154                 println("Size " + size + " bytes");
155             }
156             if (digestName != null && digest != null) {
157                 StringBuilder sb = new StringBuilder();
158                 for (byte b: digest)
159                     sb.append(String.format("%02x", b));
160                 println(digestName + " checksum " + sb);
161             }
162         }
163 
164         cm.findAttribute(Attributes.sourceFile()).ifPresent(sfa ->
165             println("Compiled from \"" + sfa.sourceFile().stringValue() + "\""));
166 
167         if (options.sysInfo || options.verbose) {
168             indent(-1);
169         }
170 
171         writeModifiers(getClassModifiers(cm.flags(), classModel.majorVersion(), classModel.minorVersion()));
172 
173         if ((classModel.flags().flagsMask() & ACC_MODULE) != 0) {
174             var attr = classModel.findAttribute(Attributes.module());
175             if (attr.isPresent()) {
176                 var modAttr = attr.get();
177                 if ((modAttr.moduleFlagsMask() & ACC_OPEN) != 0) {
178                     print("open ");
179                 }
180                 print("module ");
181                 print(() -> modAttr.moduleName().name().stringValue());
182                 if (modAttr.moduleVersion().isPresent()) {
183                     print("@");
184                     print(() -> modAttr.moduleVersion().get().stringValue());
185                 }
186             } else {
187                 // fallback for malformed class files
188                 print("class ");
189                 print(() -> getJavaName(classModel.thisClass().asInternalName()));
190             }
191         } else {

794             case '\r': return "\\r";
795             case '\\': return "\\\\";
796             case '\'': return "\\'";
797             case '\"': return "\\\"";
798             default:   return String.format("\\u%04x", (int) c);
799         }
800     }
801 
802     private Set<String> getClassModifiers(AccessFlags flags) {
803         var flagSet = flagsReportUnknown(flags, cffv());
804         Set<AccessFlag> set;
805         if (flagSet.contains(AccessFlag.INTERFACE)) {
806             set = EnumSet.copyOf(flagSet);
807             set.remove(AccessFlag.ABSTRACT);
808         } else {
809             set = flagSet;
810         }
811         return getModifiers(set);
812     }
813 
814     private Set<String> getClassModifiers(AccessFlags flags, int majorVersion, int minorVersion) {
815         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
816         Set<AccessFlag> flagSet = flagsReportUnknown(flags, cffv());
817         if (flagSet.contains(AccessFlag.INTERFACE)) {
818             flagSet = EnumSet.copyOf(flagSet);
819             flagSet.remove(AccessFlag.ABSTRACT);
820         } else if (Source.isSupported(Source.Feature.VALUE_CLASSES, majorVersion) && previewClassFile) {
821             Set<String> classModifers = getModifiers(flagSet);
822             if (!flagSet.contains(AccessFlag.IDENTITY)) {
823                 classModifers.add("value");
824             }
825             return classModifers;
826         }
827         return getModifiers(flagSet);
828     }
829 
830     private static Set<String> getModifiers(Set<AccessFlag> flags) {
831         Set<String> s = new LinkedHashSet<>();
832         for (var f : flags)
833             if (f.sourceModifier()) s.add(f == AccessFlag.STRICT ? "strictfp" : f.name().toLowerCase(Locale.ROOT));
834         return s;
835     }
836 
837     private Set<String> getClassFlags(AccessFlags flags) {
838         return getFlags(flags.flagsMask(), flagsReportUnknown(flags, cffv()));
839     }
840 
841     private static Set<String> getFlags(int mask, Set<AccessFlag> flags) {
842         Set<String> s = new LinkedHashSet<>();
843         for (var f: flags) {
844             s.add("ACC_" + f.name());
845             mask = mask & ~f.mask();
846         }
847         while (mask != 0) {
848             int bit = Integer.highestOneBit(mask);
849             s.add("0x" + Integer.toHexString(bit));
< prev index next >