Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java
58461 views
1
/*
2
* Copyright (c) 2007, 2020, 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 com.sun.tools.classfile.ClassFile;
29
import com.sun.tools.classfile.ConstantPool;
30
import com.sun.tools.classfile.ConstantPoolException;
31
32
import static com.sun.tools.classfile.ConstantPool.*;
33
34
/*
35
* Write a constant pool entry.
36
*
37
* <p><b>This is NOT part of any supported API.
38
* If you write code that depends on this, you do so at your own risk.
39
* This code and its internal interfaces are subject to change or
40
* deletion without notice.</b>
41
*/
42
public class ConstantWriter extends BasicWriter {
43
public static ConstantWriter instance(Context context) {
44
ConstantWriter instance = context.get(ConstantWriter.class);
45
if (instance == null)
46
instance = new ConstantWriter(context);
47
return instance;
48
}
49
50
protected ConstantWriter(Context context) {
51
super(context);
52
context.put(ConstantWriter.class, this);
53
classWriter = ClassWriter.instance(context);
54
options = Options.instance(context);
55
}
56
57
protected void writeConstantPool() {
58
ConstantPool constant_pool = classWriter.getClassFile().constant_pool;
59
writeConstantPool(constant_pool);
60
}
61
62
protected void writeConstantPool(ConstantPool constant_pool) {
63
ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<>() {
64
public Integer visitClass(CONSTANT_Class_info info, Void p) {
65
print("#" + info.name_index);
66
tab();
67
println("// " + stringValue(info));
68
return 1;
69
}
70
71
public Integer visitDouble(CONSTANT_Double_info info, Void p) {
72
println(stringValue(info));
73
return 2;
74
}
75
76
public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
77
print("#" + info.class_index + ".#" + info.name_and_type_index);
78
tab();
79
println("// " + stringValue(info));
80
return 1;
81
}
82
83
public Integer visitFloat(CONSTANT_Float_info info, Void p) {
84
println(stringValue(info));
85
return 1;
86
}
87
88
public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
89
println(stringValue(info));
90
return 1;
91
}
92
93
public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
94
print("#" + info.class_index + ".#" + info.name_and_type_index);
95
tab();
96
println("// " + stringValue(info));
97
return 1;
98
}
99
100
public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
101
print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index);
102
tab();
103
println("// " + stringValue(info));
104
return 1;
105
}
106
107
public Integer visitDynamicConstant(CONSTANT_Dynamic_info info, Void p) {
108
print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index);
109
tab();
110
println("// " + stringValue(info));
111
return 1;
112
}
113
114
public Integer visitLong(CONSTANT_Long_info info, Void p) {
115
println(stringValue(info));
116
return 2;
117
}
118
119
public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
120
print("#" + info.class_index + ".#" + info.name_and_type_index);
121
tab();
122
println("// " + stringValue(info));
123
return 1;
124
}
125
126
public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
127
print(info.reference_kind.tag + ":#" + info.reference_index);
128
tab();
129
println("// " + stringValue(info));
130
return 1;
131
}
132
133
public Integer visitMethodType(CONSTANT_MethodType_info info, Void p) {
134
print("#" + info.descriptor_index);
135
tab();
136
println("// " + stringValue(info));
137
return 1;
138
}
139
140
public Integer visitModule(CONSTANT_Module_info info, Void p) {
141
print("#" + info.name_index);
142
tab();
143
println("// " + stringValue(info));
144
return 1;
145
}
146
147
public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
148
print("#" + info.name_index + ":#" + info.type_index);
149
tab();
150
println("// " + stringValue(info));
151
return 1;
152
}
153
154
public Integer visitPackage(CONSTANT_Package_info info, Void p) {
155
print("#" + info.name_index);
156
tab();
157
println("// " + stringValue(info));
158
return 1;
159
}
160
161
public Integer visitString(CONSTANT_String_info info, Void p) {
162
print("#" + info.string_index);
163
tab();
164
println("// " + stringValue(info));
165
return 1;
166
}
167
168
public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
169
println(stringValue(info));
170
return 1;
171
}
172
173
};
174
println("Constant pool:");
175
indent(+1);
176
int width = String.valueOf(constant_pool.size()).length() + 1;
177
int cpx = 1;
178
while (cpx < constant_pool.size()) {
179
print(String.format("%" + width + "s", ("#" + cpx)));
180
try {
181
CPInfo cpInfo = constant_pool.get(cpx);
182
print(String.format(" = %-18s ", cpTagName(cpInfo)));
183
cpx += cpInfo.accept(v, null);
184
} catch (ConstantPool.InvalidIndex ex) {
185
// should not happen
186
}
187
}
188
indent(-1);
189
}
190
191
protected void write(int cpx) {
192
ClassFile classFile = classWriter.getClassFile();
193
if (cpx == 0) {
194
print("#0");
195
return;
196
}
197
198
CPInfo cpInfo;
199
try {
200
cpInfo = classFile.constant_pool.get(cpx);
201
} catch (ConstantPoolException e) {
202
print("#" + cpx);
203
return;
204
}
205
206
int tag = cpInfo.getTag();
207
switch (tag) {
208
case CONSTANT_Methodref:
209
case CONSTANT_InterfaceMethodref:
210
case CONSTANT_Fieldref:
211
// simplify references within this class
212
CPRefInfo ref = (CPRefInfo) cpInfo;
213
try {
214
if (ref.class_index == classFile.this_class)
215
cpInfo = classFile.constant_pool.get(ref.name_and_type_index);
216
} catch (ConstantPool.InvalidIndex e) {
217
// ignore, for now
218
}
219
}
220
print(tagName(tag) + " " + stringValue(cpInfo));
221
}
222
223
String cpTagName(CPInfo cpInfo) {
224
String n = cpInfo.getClass().getSimpleName();
225
return n.replace("CONSTANT_", "").replace("_info", "");
226
}
227
228
String tagName(int tag) {
229
switch (tag) {
230
case CONSTANT_Utf8:
231
return "Utf8";
232
case CONSTANT_Integer:
233
return "int";
234
case CONSTANT_Float:
235
return "float";
236
case CONSTANT_Long:
237
return "long";
238
case CONSTANT_Double:
239
return "double";
240
case CONSTANT_Class:
241
return "class";
242
case CONSTANT_String:
243
return "String";
244
case CONSTANT_Fieldref:
245
return "Field";
246
case CONSTANT_MethodHandle:
247
return "MethodHandle";
248
case CONSTANT_MethodType:
249
return "MethodType";
250
case CONSTANT_Methodref:
251
return "Method";
252
case CONSTANT_InterfaceMethodref:
253
return "InterfaceMethod";
254
case CONSTANT_InvokeDynamic:
255
return "InvokeDynamic";
256
case CONSTANT_Dynamic:
257
return "Dynamic";
258
case CONSTANT_NameAndType:
259
return "NameAndType";
260
default:
261
return "(unknown tag " + tag + ")";
262
}
263
}
264
265
String booleanValue(int constant_pool_index) {
266
ClassFile classFile = classWriter.getClassFile();
267
try {
268
CPInfo info = classFile.constant_pool.get(constant_pool_index);
269
if (info instanceof CONSTANT_Integer_info) {
270
int value = ((CONSTANT_Integer_info) info).value;
271
switch (value) {
272
case 0: return "false";
273
case 1: return "true";
274
}
275
}
276
return "#" + constant_pool_index;
277
} catch (ConstantPool.InvalidIndex e) {
278
return report(e);
279
}
280
}
281
282
String charValue(int constant_pool_index) {
283
ClassFile classFile = classWriter.getClassFile();
284
try {
285
CPInfo info = classFile.constant_pool.get(constant_pool_index);
286
if (info instanceof CONSTANT_Integer_info) {
287
int value = ((CONSTANT_Integer_info) info).value;
288
return String.valueOf((char) value);
289
} else {
290
return "#" + constant_pool_index;
291
}
292
} catch (ConstantPool.InvalidIndex e) {
293
return report(e);
294
}
295
}
296
297
String stringValue(int constant_pool_index) {
298
ClassFile classFile = classWriter.getClassFile();
299
try {
300
return stringValue(classFile.constant_pool.get(constant_pool_index));
301
} catch (ConstantPool.InvalidIndex e) {
302
return report(e);
303
}
304
}
305
306
String stringValue(CPInfo cpInfo) {
307
return stringValueVisitor.visit(cpInfo);
308
}
309
310
StringValueVisitor stringValueVisitor = new StringValueVisitor();
311
312
private class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
313
public String visit(CPInfo info) {
314
return info.accept(this, null);
315
}
316
317
public String visitClass(CONSTANT_Class_info info, Void p) {
318
return getCheckedName(info);
319
}
320
321
String getCheckedName(CONSTANT_Class_info info) {
322
try {
323
return checkName(info.getName());
324
} catch (ConstantPoolException e) {
325
return report(e);
326
}
327
}
328
329
public String visitDouble(CONSTANT_Double_info info, Void p) {
330
return info.value + "d";
331
}
332
333
public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
334
return visitRef(info, p);
335
}
336
337
public String visitFloat(CONSTANT_Float_info info, Void p) {
338
return info.value + "f";
339
}
340
341
public String visitInteger(CONSTANT_Integer_info info, Void p) {
342
return String.valueOf(info.value);
343
}
344
345
public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
346
return visitRef(info, p);
347
}
348
349
public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
350
try {
351
String callee = stringValue(info.getNameAndTypeInfo());
352
return "#" + info.bootstrap_method_attr_index + ":" + callee;
353
} catch (ConstantPoolException e) {
354
return report(e);
355
}
356
}
357
358
public String visitDynamicConstant(CONSTANT_Dynamic_info info, Void p) {
359
try {
360
String callee = stringValue(info.getNameAndTypeInfo());
361
return "#" + info.bootstrap_method_attr_index + ":" + callee;
362
} catch (ConstantPoolException e) {
363
return report(e);
364
}
365
}
366
367
public String visitLong(CONSTANT_Long_info info, Void p) {
368
return info.value + "l";
369
}
370
371
public String visitModule(CONSTANT_Module_info info, Void p) {
372
try {
373
return checkName(info.getName());
374
} catch (ConstantPoolException e) {
375
return report(e);
376
}
377
}
378
379
public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
380
return getCheckedName(info) + ":" + getType(info);
381
}
382
383
String getCheckedName(CONSTANT_NameAndType_info info) {
384
try {
385
return checkName(info.getName());
386
} catch (ConstantPoolException e) {
387
return report(e);
388
}
389
}
390
391
public String visitPackage(CONSTANT_Package_info info, Void p) {
392
try {
393
return checkName(info.getName());
394
} catch (ConstantPoolException e) {
395
return report(e);
396
}
397
}
398
399
String getType(CONSTANT_NameAndType_info info) {
400
try {
401
return info.getType();
402
} catch (ConstantPoolException e) {
403
return report(e);
404
}
405
}
406
407
public String visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
408
try {
409
return info.reference_kind + " " + stringValue(info.getCPRefInfo());
410
} catch (ConstantPoolException e) {
411
return report(e);
412
}
413
}
414
415
public String visitMethodType(CONSTANT_MethodType_info info, Void p) {
416
try {
417
return info.getType();
418
} catch (ConstantPoolException e) {
419
return report(e);
420
}
421
}
422
423
public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
424
return visitRef(info, p);
425
}
426
427
public String visitString(CONSTANT_String_info info, Void p) {
428
try {
429
ClassFile classFile = classWriter.getClassFile();
430
int string_index = info.string_index;
431
return stringValue(classFile.constant_pool.getUTF8Info(string_index));
432
} catch (ConstantPoolException e) {
433
return report(e);
434
}
435
}
436
437
public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
438
String s = info.value;
439
StringBuilder sb = new StringBuilder();
440
for (int i = 0; i < s.length(); i++) {
441
char c = s.charAt(i);
442
switch (c) {
443
case '\t':
444
sb.append('\\').append('t');
445
break;
446
case '\n':
447
sb.append('\\').append('n');
448
break;
449
case '\r':
450
sb.append('\\').append('r');
451
break;
452
case '\b':
453
sb.append('\\').append('b');
454
break;
455
case '\f':
456
sb.append('\\').append('f');
457
break;
458
case '\"':
459
sb.append('\\').append('\"');
460
break;
461
case '\'':
462
sb.append('\\').append('\'');
463
break;
464
case '\\':
465
sb.append('\\').append('\\');
466
break;
467
default:
468
if (Character.isISOControl(c)) {
469
sb.append(String.format("\\u%04x", (int) c));
470
break;
471
}
472
sb.append(c);
473
}
474
}
475
return sb.toString();
476
}
477
478
String visitRef(CPRefInfo info, Void p) {
479
String cn = getCheckedClassName(info);
480
String nat;
481
try {
482
nat = stringValue(info.getNameAndTypeInfo());
483
} catch (ConstantPoolException e) {
484
nat = report(e);
485
}
486
return cn + "." + nat;
487
}
488
489
String getCheckedClassName(CPRefInfo info) {
490
try {
491
return checkName(info.getClassName());
492
} catch (ConstantPoolException e) {
493
return report(e);
494
}
495
}
496
}
497
498
/* If name is a valid binary name, return it; otherwise quote it. */
499
private static String checkName(String name) {
500
if (name == null)
501
return "null";
502
503
int len = name.length();
504
if (len == 0)
505
return "\"\"";
506
507
int cc = '/';
508
int cp;
509
for (int k = 0; k < len; k += Character.charCount(cp)) {
510
cp = name.codePointAt(k);
511
if ((cc == '/' && !Character.isJavaIdentifierStart(cp))
512
|| (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
513
return "\"" + addEscapes(name) + "\"";
514
}
515
cc = cp;
516
}
517
518
return name;
519
}
520
521
/* If name requires escapes, put them in, so it can be a string body. */
522
private static String addEscapes(String name) {
523
String esc = "\\\"\n\t";
524
String rep = "\\\"nt";
525
StringBuilder buf = null;
526
int nextk = 0;
527
int len = name.length();
528
for (int k = 0; k < len; k++) {
529
char cp = name.charAt(k);
530
int n = esc.indexOf(cp);
531
if (n >= 0) {
532
if (buf == null)
533
buf = new StringBuilder(len * 2);
534
if (nextk < k)
535
buf.append(name, nextk, k);
536
buf.append('\\');
537
buf.append(rep.charAt(n));
538
nextk = k+1;
539
}
540
}
541
if (buf == null)
542
return name;
543
if (nextk < len)
544
buf.append(name, nextk, len);
545
return buf.toString();
546
}
547
548
private final ClassWriter classWriter;
549
private final Options options;
550
}
551
552