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

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

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

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














815     private static Set<String> getModifiers(Set<AccessFlag> flags) {
816         Set<String> s = new LinkedHashSet<>();
817         for (var f : flags)
818             if (f.sourceModifier()) s.add(Modifier.toString(f.mask()));
819         return s;
820     }
821 
822     private Set<String> getClassFlags(AccessFlags flags) {
823         return getFlags(flags.flagsMask(), flagsReportUnknown(flags, cffv()));
824     }
825 
826     private static Set<String> getFlags(int mask, Set<AccessFlag> flags) {
827         Set<String> s = new LinkedHashSet<>();
828         for (var f: flags) {
829             s.add("ACC_" + f.name());
830             mask = mask & ~f.mask();
831         }
832         while (mask != 0) {
833             int bit = Integer.highestOneBit(mask);
834             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;

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

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(), classModel.majorVersion(), classModel.minorVersion()));
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 {

796             case '\r': return "\\r";
797             case '\\': return "\\\\";
798             case '\'': return "\\'";
799             case '\"': return "\\\"";
800             default:   return String.format("\\u%04x", (int) c);
801         }
802     }
803 
804     private Set<String> getClassModifiers(AccessFlags flags) {
805         var flagSet = flagsReportUnknown(flags, cffv());
806         Set<AccessFlag> set;
807         if (flagSet.contains(AccessFlag.INTERFACE)) {
808             set = EnumSet.copyOf(flagSet);
809             set.remove(AccessFlag.ABSTRACT);
810         } else {
811             set = flagSet;
812         }
813         return getModifiers(set);
814     }
815 
816     private Set<String> getClassModifiers(AccessFlags flags, int majorVersion, int minorVersion) {
817         boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
818         Set<AccessFlag> flagSet = flagsReportUnknown(flags, cffv());
819         if (flagSet.contains(AccessFlag.INTERFACE)) {
820             flagSet = EnumSet.copyOf(flagSet);
821             flagSet.remove(AccessFlag.ABSTRACT);
822         } else if (Source.isSupported(Source.Feature.VALUE_CLASSES, majorVersion) && previewClassFile) {
823             Set<String> classModifers = getModifiers(flagSet);
824             classModifers.add("value");
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(Modifier.toString(f.mask()));
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 >