Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java
38899 views
1
/*
2
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
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.net.URI;
29
import java.text.DateFormat;
30
import java.util.Collection;
31
import java.util.Date;
32
import java.util.List;
33
34
import com.sun.tools.classfile.AccessFlags;
35
import com.sun.tools.classfile.Attribute;
36
import com.sun.tools.classfile.Attributes;
37
import com.sun.tools.classfile.ClassFile;
38
import com.sun.tools.classfile.Code_attribute;
39
import com.sun.tools.classfile.ConstantPool;
40
import com.sun.tools.classfile.ConstantPoolException;
41
import com.sun.tools.classfile.ConstantValue_attribute;
42
import com.sun.tools.classfile.Descriptor;
43
import com.sun.tools.classfile.DescriptorException;
44
import com.sun.tools.classfile.Exceptions_attribute;
45
import com.sun.tools.classfile.Field;
46
import com.sun.tools.classfile.Method;
47
import com.sun.tools.classfile.Signature;
48
import com.sun.tools.classfile.Signature_attribute;
49
import com.sun.tools.classfile.SourceFile_attribute;
50
import com.sun.tools.classfile.Type;
51
import com.sun.tools.classfile.Type.ArrayType;
52
import com.sun.tools.classfile.Type.ClassSigType;
53
import com.sun.tools.classfile.Type.ClassType;
54
import com.sun.tools.classfile.Type.MethodType;
55
import com.sun.tools.classfile.Type.SimpleType;
56
import com.sun.tools.classfile.Type.TypeParamType;
57
import com.sun.tools.classfile.Type.WildcardType;
58
59
import static com.sun.tools.classfile.AccessFlags.*;
60
61
/*
62
* The main javap class to write the contents of a class file as text.
63
*
64
* <p><b>This is NOT part of any supported API.
65
* If you write code that depends on this, you do so at your own risk.
66
* This code and its internal interfaces are subject to change or
67
* deletion without notice.</b>
68
*/
69
public class ClassWriter extends BasicWriter {
70
static ClassWriter instance(Context context) {
71
ClassWriter instance = context.get(ClassWriter.class);
72
if (instance == null)
73
instance = new ClassWriter(context);
74
return instance;
75
}
76
77
protected ClassWriter(Context context) {
78
super(context);
79
context.put(ClassWriter.class, this);
80
options = Options.instance(context);
81
attrWriter = AttributeWriter.instance(context);
82
codeWriter = CodeWriter.instance(context);
83
constantWriter = ConstantWriter.instance(context);
84
}
85
86
void setDigest(String name, byte[] digest) {
87
this.digestName = name;
88
this.digest = digest;
89
}
90
91
void setFile(URI uri) {
92
this.uri = uri;
93
}
94
95
void setFileSize(int size) {
96
this.size = size;
97
}
98
99
void setLastModified(long lastModified) {
100
this.lastModified = lastModified;
101
}
102
103
protected ClassFile getClassFile() {
104
return classFile;
105
}
106
107
protected void setClassFile(ClassFile cf) {
108
classFile = cf;
109
constant_pool = classFile.constant_pool;
110
}
111
112
protected Method getMethod() {
113
return method;
114
}
115
116
protected void setMethod(Method m) {
117
method = m;
118
}
119
120
public void write(ClassFile cf) {
121
setClassFile(cf);
122
123
if (options.sysInfo || options.verbose) {
124
if (uri != null) {
125
if (uri.getScheme().equals("file"))
126
println("Classfile " + uri.getPath());
127
else
128
println("Classfile " + uri);
129
}
130
indent(+1);
131
if (lastModified != -1) {
132
Date lm = new Date(lastModified);
133
DateFormat df = DateFormat.getDateInstance();
134
if (size > 0) {
135
println("Last modified " + df.format(lm) + "; size " + size + " bytes");
136
} else {
137
println("Last modified " + df.format(lm));
138
}
139
} else if (size > 0) {
140
println("Size " + size + " bytes");
141
}
142
if (digestName != null && digest != null) {
143
StringBuilder sb = new StringBuilder();
144
for (byte b: digest)
145
sb.append(String.format("%02x", b));
146
println(digestName + " checksum " + sb);
147
}
148
}
149
150
Attribute sfa = cf.getAttribute(Attribute.SourceFile);
151
if (sfa instanceof SourceFile_attribute) {
152
println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\"");
153
}
154
155
if (options.sysInfo || options.verbose) {
156
indent(-1);
157
}
158
159
String name = getJavaName(classFile);
160
AccessFlags flags = cf.access_flags;
161
162
writeModifiers(flags.getClassModifiers());
163
164
if (classFile.isClass())
165
print("class ");
166
else if (classFile.isInterface())
167
print("interface ");
168
169
print(name);
170
171
Signature_attribute sigAttr = getSignature(cf.attributes);
172
if (sigAttr == null) {
173
// use info from class file header
174
if (classFile.isClass() && classFile.super_class != 0 ) {
175
String sn = getJavaSuperclassName(cf);
176
if (!sn.equals("java.lang.Object")) {
177
print(" extends ");
178
print(sn);
179
}
180
}
181
for (int i = 0; i < classFile.interfaces.length; i++) {
182
print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ",");
183
print(getJavaInterfaceName(classFile, i));
184
}
185
} else {
186
try {
187
Type t = sigAttr.getParsedSignature().getType(constant_pool);
188
JavaTypePrinter p = new JavaTypePrinter(classFile.isInterface());
189
// The signature parser cannot disambiguate between a
190
// FieldType and a ClassSignatureType that only contains a superclass type.
191
if (t instanceof Type.ClassSigType) {
192
print(p.print(t));
193
} else if (options.verbose || !t.isObject()) {
194
print(" extends ");
195
print(p.print(t));
196
}
197
} catch (ConstantPoolException e) {
198
print(report(e));
199
}
200
}
201
202
if (options.verbose) {
203
println();
204
indent(+1);
205
println("minor version: " + cf.minor_version);
206
println("major version: " + cf.major_version);
207
writeList("flags: ", flags.getClassFlags(), "\n");
208
indent(-1);
209
constantWriter.writeConstantPool();
210
} else {
211
print(" ");
212
}
213
214
println("{");
215
indent(+1);
216
writeFields();
217
writeMethods();
218
indent(-1);
219
println("}");
220
221
if (options.verbose) {
222
attrWriter.write(cf, cf.attributes, constant_pool);
223
}
224
}
225
// where
226
class JavaTypePrinter implements Type.Visitor<StringBuilder,StringBuilder> {
227
boolean isInterface;
228
229
JavaTypePrinter(boolean isInterface) {
230
this.isInterface = isInterface;
231
}
232
233
String print(Type t) {
234
return t.accept(this, new StringBuilder()).toString();
235
}
236
237
String printTypeArgs(List<? extends TypeParamType> typeParamTypes) {
238
StringBuilder builder = new StringBuilder();
239
appendIfNotEmpty(builder, "<", typeParamTypes, "> ");
240
return builder.toString();
241
}
242
243
public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) {
244
sb.append(getJavaName(type.name));
245
return sb;
246
}
247
248
public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) {
249
append(sb, type.elemType);
250
sb.append("[]");
251
return sb;
252
}
253
254
public StringBuilder visitMethodType(MethodType type, StringBuilder sb) {
255
appendIfNotEmpty(sb, "<", type.typeParamTypes, "> ");
256
append(sb, type.returnType);
257
append(sb, " (", type.paramTypes, ")");
258
appendIfNotEmpty(sb, " throws ", type.throwsTypes, "");
259
return sb;
260
}
261
262
public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) {
263
appendIfNotEmpty(sb, "<", type.typeParamTypes, ">");
264
if (isInterface) {
265
appendIfNotEmpty(sb, " extends ", type.superinterfaceTypes, "");
266
} else {
267
if (type.superclassType != null
268
&& (options.verbose || !type.superclassType.isObject())) {
269
sb.append(" extends ");
270
append(sb, type.superclassType);
271
}
272
appendIfNotEmpty(sb, " implements ", type.superinterfaceTypes, "");
273
}
274
return sb;
275
}
276
277
public StringBuilder visitClassType(ClassType type, StringBuilder sb) {
278
if (type.outerType != null) {
279
append(sb, type.outerType);
280
sb.append(".");
281
}
282
sb.append(getJavaName(type.name));
283
appendIfNotEmpty(sb, "<", type.typeArgs, ">");
284
return sb;
285
}
286
287
public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) {
288
sb.append(type.name);
289
String sep = " extends ";
290
if (type.classBound != null
291
&& (options.verbose || !type.classBound.isObject())) {
292
sb.append(sep);
293
append(sb, type.classBound);
294
sep = " & ";
295
}
296
if (type.interfaceBounds != null) {
297
for (Type bound: type.interfaceBounds) {
298
sb.append(sep);
299
append(sb, bound);
300
sep = " & ";
301
}
302
}
303
return sb;
304
}
305
306
public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) {
307
switch (type.kind) {
308
case UNBOUNDED:
309
sb.append("?");
310
break;
311
case EXTENDS:
312
sb.append("? extends ");
313
append(sb, type.boundType);
314
break;
315
case SUPER:
316
sb.append("? super ");
317
append(sb, type.boundType);
318
break;
319
default:
320
throw new AssertionError();
321
}
322
return sb;
323
}
324
325
private void append(StringBuilder sb, Type t) {
326
t.accept(this, sb);
327
}
328
329
private void append(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
330
sb.append(prefix);
331
String sep = "";
332
for (Type t: list) {
333
sb.append(sep);
334
append(sb, t);
335
sep = ", ";
336
}
337
sb.append(suffix);
338
}
339
340
private void appendIfNotEmpty(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
341
if (!isEmpty(list))
342
append(sb, prefix, list, suffix);
343
}
344
345
private boolean isEmpty(List<? extends Type> list) {
346
return (list == null || list.isEmpty());
347
}
348
}
349
350
protected void writeFields() {
351
for (Field f: classFile.fields) {
352
writeField(f);
353
}
354
}
355
356
protected void writeField(Field f) {
357
if (!options.checkAccess(f.access_flags))
358
return;
359
360
AccessFlags flags = f.access_flags;
361
writeModifiers(flags.getFieldModifiers());
362
Signature_attribute sigAttr = getSignature(f.attributes);
363
if (sigAttr == null)
364
print(getJavaFieldType(f.descriptor));
365
else {
366
try {
367
Type t = sigAttr.getParsedSignature().getType(constant_pool);
368
print(getJavaName(t.toString()));
369
} catch (ConstantPoolException e) {
370
// report error?
371
// fall back on non-generic descriptor
372
print(getJavaFieldType(f.descriptor));
373
}
374
}
375
print(" ");
376
print(getFieldName(f));
377
if (options.showConstants) {
378
Attribute a = f.attributes.get(Attribute.ConstantValue);
379
if (a instanceof ConstantValue_attribute) {
380
print(" = ");
381
ConstantValue_attribute cv = (ConstantValue_attribute) a;
382
print(getConstantValue(f.descriptor, cv.constantvalue_index));
383
}
384
}
385
print(";");
386
println();
387
388
indent(+1);
389
390
boolean showBlank = false;
391
392
if (options.showDescriptors)
393
println("descriptor: " + getValue(f.descriptor));
394
395
if (options.verbose)
396
writeList("flags: ", flags.getFieldFlags(), "\n");
397
398
if (options.showAllAttrs) {
399
for (Attribute attr: f.attributes)
400
attrWriter.write(f, attr, constant_pool);
401
showBlank = true;
402
}
403
404
indent(-1);
405
406
if (showBlank || options.showDisassembled || options.showLineAndLocalVariableTables)
407
println();
408
}
409
410
protected void writeMethods() {
411
for (Method m: classFile.methods)
412
writeMethod(m);
413
setPendingNewline(false);
414
}
415
416
protected void writeMethod(Method m) {
417
if (!options.checkAccess(m.access_flags))
418
return;
419
420
method = m;
421
422
AccessFlags flags = m.access_flags;
423
424
Descriptor d;
425
Type.MethodType methodType;
426
List<? extends Type> methodExceptions;
427
428
Signature_attribute sigAttr = getSignature(m.attributes);
429
if (sigAttr == null) {
430
d = m.descriptor;
431
methodType = null;
432
methodExceptions = null;
433
} else {
434
Signature methodSig = sigAttr.getParsedSignature();
435
d = methodSig;
436
try {
437
methodType = (Type.MethodType) methodSig.getType(constant_pool);
438
methodExceptions = methodType.throwsTypes;
439
if (methodExceptions != null && methodExceptions.isEmpty())
440
methodExceptions = null;
441
} catch (ConstantPoolException e) {
442
// report error?
443
// fall back on standard descriptor
444
methodType = null;
445
methodExceptions = null;
446
}
447
}
448
449
writeModifiers(flags.getMethodModifiers());
450
if (methodType != null) {
451
print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes));
452
}
453
if (getName(m).equals("<init>")) {
454
print(getJavaName(classFile));
455
print(getJavaParameterTypes(d, flags));
456
} else if (getName(m).equals("<clinit>")) {
457
print("{}");
458
} else {
459
print(getJavaReturnType(d));
460
print(" ");
461
print(getName(m));
462
print(getJavaParameterTypes(d, flags));
463
}
464
465
Attribute e_attr = m.attributes.get(Attribute.Exceptions);
466
if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions
467
if (e_attr instanceof Exceptions_attribute) {
468
Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
469
print(" throws ");
470
if (methodExceptions != null) { // use generic list if available
471
writeList("", methodExceptions, "");
472
} else {
473
for (int i = 0; i < exceptions.number_of_exceptions; i++) {
474
if (i > 0)
475
print(", ");
476
print(getJavaException(exceptions, i));
477
}
478
}
479
} else {
480
report("Unexpected or invalid value for Exceptions attribute");
481
}
482
}
483
484
println(";");
485
486
indent(+1);
487
488
if (options.showDescriptors) {
489
println("descriptor: " + getValue(m.descriptor));
490
}
491
492
if (options.verbose) {
493
writeList("flags: ", flags.getMethodFlags(), "\n");
494
}
495
496
Code_attribute code = null;
497
Attribute c_attr = m.attributes.get(Attribute.Code);
498
if (c_attr != null) {
499
if (c_attr instanceof Code_attribute)
500
code = (Code_attribute) c_attr;
501
else
502
report("Unexpected or invalid value for Code attribute");
503
}
504
505
if (options.showAllAttrs) {
506
Attribute[] attrs = m.attributes.attrs;
507
for (Attribute attr: attrs)
508
attrWriter.write(m, attr, constant_pool);
509
} else if (code != null) {
510
if (options.showDisassembled) {
511
println("Code:");
512
codeWriter.writeInstrs(code);
513
codeWriter.writeExceptionTable(code);
514
}
515
516
if (options.showLineAndLocalVariableTables) {
517
attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool);
518
attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool);
519
}
520
}
521
522
indent(-1);
523
524
// set pendingNewline to write a newline before the next method (if any)
525
// if a separator is desired
526
setPendingNewline(
527
options.showDisassembled ||
528
options.showAllAttrs ||
529
options.showDescriptors ||
530
options.showLineAndLocalVariableTables ||
531
options.verbose);
532
}
533
534
void writeModifiers(Collection<String> items) {
535
for (Object item: items) {
536
print(item);
537
print(" ");
538
}
539
}
540
541
void writeList(String prefix, Collection<?> items, String suffix) {
542
print(prefix);
543
String sep = "";
544
for (Object item: items) {
545
print(sep);
546
print(item);
547
sep = ", ";
548
}
549
print(suffix);
550
}
551
552
void writeListIfNotEmpty(String prefix, List<?> items, String suffix) {
553
if (items != null && items.size() > 0)
554
writeList(prefix, items, suffix);
555
}
556
557
Signature_attribute getSignature(Attributes attributes) {
558
return (Signature_attribute) attributes.get(Attribute.Signature);
559
}
560
561
String adjustVarargs(AccessFlags flags, String params) {
562
if (flags.is(ACC_VARARGS)) {
563
int i = params.lastIndexOf("[]");
564
if (i > 0)
565
return params.substring(0, i) + "..." + params.substring(i+2);
566
}
567
568
return params;
569
}
570
571
String getJavaName(ClassFile cf) {
572
try {
573
return getJavaName(cf.getName());
574
} catch (ConstantPoolException e) {
575
return report(e);
576
}
577
}
578
579
String getJavaSuperclassName(ClassFile cf) {
580
try {
581
return getJavaName(cf.getSuperclassName());
582
} catch (ConstantPoolException e) {
583
return report(e);
584
}
585
}
586
587
String getJavaInterfaceName(ClassFile cf, int index) {
588
try {
589
return getJavaName(cf.getInterfaceName(index));
590
} catch (ConstantPoolException e) {
591
return report(e);
592
}
593
}
594
595
String getJavaFieldType(Descriptor d) {
596
try {
597
return getJavaName(d.getFieldType(constant_pool));
598
} catch (ConstantPoolException e) {
599
return report(e);
600
} catch (DescriptorException e) {
601
return report(e);
602
}
603
}
604
605
String getJavaReturnType(Descriptor d) {
606
try {
607
return getJavaName(d.getReturnType(constant_pool));
608
} catch (ConstantPoolException e) {
609
return report(e);
610
} catch (DescriptorException e) {
611
return report(e);
612
}
613
}
614
615
String getJavaParameterTypes(Descriptor d, AccessFlags flags) {
616
try {
617
return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool)));
618
} catch (ConstantPoolException e) {
619
return report(e);
620
} catch (DescriptorException e) {
621
return report(e);
622
}
623
}
624
625
String getJavaException(Exceptions_attribute attr, int index) {
626
try {
627
return getJavaName(attr.getException(index, constant_pool));
628
} catch (ConstantPoolException e) {
629
return report(e);
630
}
631
}
632
633
String getValue(Descriptor d) {
634
try {
635
return d.getValue(constant_pool);
636
} catch (ConstantPoolException e) {
637
return report(e);
638
}
639
}
640
641
String getFieldName(Field f) {
642
try {
643
return f.getName(constant_pool);
644
} catch (ConstantPoolException e) {
645
return report(e);
646
}
647
}
648
649
String getName(Method m) {
650
try {
651
return m.getName(constant_pool);
652
} catch (ConstantPoolException e) {
653
return report(e);
654
}
655
}
656
657
static String getJavaName(String name) {
658
return name.replace('/', '.');
659
}
660
661
String getSourceFile(SourceFile_attribute attr) {
662
try {
663
return attr.getSourceFile(constant_pool);
664
} catch (ConstantPoolException e) {
665
return report(e);
666
}
667
}
668
669
/**
670
* Get the value of an entry in the constant pool as a Java constant.
671
* Characters and booleans are represented by CONSTANT_Intgere entries.
672
* Character and string values are processed to escape characters outside
673
* the basic printable ASCII set.
674
* @param d the descriptor, giving the expected type of the constant
675
* @param index the index of the value in the constant pool
676
* @return a printable string containing the value of the constant.
677
*/
678
String getConstantValue(Descriptor d, int index) {
679
try {
680
ConstantPool.CPInfo cpInfo = constant_pool.get(index);
681
682
switch (cpInfo.getTag()) {
683
case ConstantPool.CONSTANT_Integer: {
684
ConstantPool.CONSTANT_Integer_info info =
685
(ConstantPool.CONSTANT_Integer_info) cpInfo;
686
String t = d.getValue(constant_pool);
687
if (t.equals("C")) { // character
688
return getConstantCharValue((char) info.value);
689
} else if (t.equals("Z")) { // boolean
690
return String.valueOf(info.value == 1);
691
} else { // other: assume integer
692
return String.valueOf(info.value);
693
}
694
}
695
696
case ConstantPool.CONSTANT_String: {
697
ConstantPool.CONSTANT_String_info info =
698
(ConstantPool.CONSTANT_String_info) cpInfo;
699
return getConstantStringValue(info.getString());
700
}
701
702
default:
703
return constantWriter.stringValue(cpInfo);
704
}
705
} catch (ConstantPoolException e) {
706
return "#" + index;
707
}
708
}
709
710
private String getConstantCharValue(char c) {
711
StringBuilder sb = new StringBuilder();
712
sb.append('\'');
713
sb.append(esc(c, '\''));
714
sb.append('\'');
715
return sb.toString();
716
}
717
718
private String getConstantStringValue(String s) {
719
StringBuilder sb = new StringBuilder();
720
sb.append("\"");
721
for (int i = 0; i < s.length(); i++) {
722
sb.append(esc(s.charAt(i), '"'));
723
}
724
sb.append("\"");
725
return sb.toString();
726
}
727
728
private String esc(char c, char quote) {
729
if (32 <= c && c <= 126 && c != quote)
730
return String.valueOf(c);
731
else switch (c) {
732
case '\b': return "\\b";
733
case '\n': return "\\n";
734
case '\t': return "\\t";
735
case '\f': return "\\f";
736
case '\r': return "\\r";
737
case '\\': return "\\\\";
738
case '\'': return "\\'";
739
case '\"': return "\\\"";
740
default: return String.format("\\u%04x", (int) c);
741
}
742
}
743
744
private Options options;
745
private AttributeWriter attrWriter;
746
private CodeWriter codeWriter;
747
private ConstantWriter constantWriter;
748
private ClassFile classFile;
749
private URI uri;
750
private long lastModified;
751
private String digestName;
752
private byte[] digest;
753
private int size;
754
private ConstantPool constant_pool;
755
private Method method;
756
}
757
758