1 /* 2 * Copyright (c) 2007, 2024, 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.lang.reflect.Modifier; 29 import java.nio.charset.StandardCharsets; 30 import java.util.List; 31 import java.util.Locale; 32 import java.lang.classfile.*; 33 import java.lang.reflect.AccessFlag; 34 import java.lang.classfile.constantpool.*; 35 import java.lang.classfile.attribute.*; 36 import static java.lang.classfile.ClassFile.*; 37 import static java.lang.classfile.attribute.StackMapFrameInfo.*; 38 import static java.lang.classfile.instruction.CharacterRange.*; 39 40 /* 41 * A writer for writing Attributes as text. 42 * 43 * <p><b>This is NOT part of any supported API. 44 * If you write code that depends on this, you do so at your own risk. 45 * This code and its internal interfaces are subject to change or 46 * deletion without notice.</b> 47 */ 48 public class AttributeWriter extends BasicWriter { 49 50 public static AttributeWriter instance(Context context) { 51 AttributeWriter instance = context.get(AttributeWriter.class); 52 if (instance == null) 53 instance = new AttributeWriter(context); 54 return instance; 55 } 56 57 protected AttributeWriter(Context context) { 58 super(context); 59 context.put(AttributeWriter.class, this); 60 annotationWriter = AnnotationWriter.instance(context); 61 codeWriter = CodeWriter.instance(context); 62 constantWriter = ConstantWriter.instance(context); 63 options = Options.instance(context); 64 } 65 66 public void write(List<Attribute<?>> attrs) { 67 write(attrs, null); 68 } 69 70 public void write(List<Attribute<?>> attrs, CodeAttribute lr) { 71 if (attrs != null) { 72 for (var attr : attrs) try { 73 write(attr, lr); 74 } catch (IllegalArgumentException e) { 75 report(e); 76 } 77 } 78 } 79 80 public void write(Attribute<?> a, CodeAttribute lr) { 81 switch (a) { 82 case UnknownAttribute attr -> { 83 byte[] data = attr.contents(); 84 int i = 0; 85 int j = 0; 86 print(" "); 87 print(attr.attributeName()); 88 print(": "); 89 print("length = 0x" + toHex(data.length)); 90 print(" (unknown attribute)"); 91 println(); 92 print(" "); 93 while (i < data.length) { 94 print(toHex(data[i], 2)); 95 96 j++; 97 if (j == 16) { 98 println(); 99 print(" "); 100 j = 0; 101 } else { 102 print(" "); 103 } 104 i++; 105 } 106 println(); 107 } 108 case AnnotationDefaultAttribute attr -> { 109 println("AnnotationDefault:"); 110 indent(+1); 111 print("default_value: "); 112 annotationWriter.write(attr.defaultValue()); 113 indent(-1); 114 println(); 115 } 116 case BootstrapMethodsAttribute attr -> { 117 println("BootstrapMethods:"); 118 for (int i = 0; i < attr.bootstrapMethodsSize() ; i++) { 119 var bsm = attr.bootstrapMethods().get(i); 120 indent(+1); 121 print(i + ": #" + bsm.bootstrapMethod().index() + " "); 122 println(constantWriter.stringValue(bsm.bootstrapMethod())); 123 indent(+1); 124 println("Method arguments:"); 125 indent(+1); 126 for (var arg : bsm.arguments()) { 127 print("#" + arg.index() + " "); 128 println(constantWriter.stringValue(arg)); 129 } 130 indent(-3); 131 } 132 } 133 case CharacterRangeTableAttribute attr -> { 134 println("CharacterRangeTable:"); 135 indent(+1); 136 for (var e : attr.characterRangeTable()) { 137 print(String.format(" %2d, %2d, %6x, %6x, %4x", 138 e.startPc(), e.endPc(), 139 e.characterRangeStart(), e.characterRangeEnd(), 140 e.flags())); 141 tab(); 142 print(String.format("// %2d, %2d, %4d:%02d, %4d:%02d", 143 e.startPc(), e.endPc(), 144 (e.characterRangeStart() >> 10), 145 (e.characterRangeStart() & 0x3ff), 146 (e.characterRangeEnd() >> 10), 147 (e.characterRangeEnd() & 0x3ff))); 148 if ((e.flags() & FLAG_STATEMENT) != 0) 149 print(", statement"); 150 if ((e.flags() & FLAG_BLOCK) != 0) 151 print(", block"); 152 if ((e.flags() & FLAG_ASSIGNMENT) != 0) 153 print(", assignment"); 154 if ((e.flags() & FLAG_FLOW_CONTROLLER) != 0) 155 print(", flow-controller"); 156 if ((e.flags() & FLAG_FLOW_TARGET) != 0) 157 print(", flow-target"); 158 if ((e.flags() & FLAG_INVOKE) != 0) 159 print(", invoke"); 160 if ((e.flags() & FLAG_CREATE) != 0) 161 print(", create"); 162 if ((e.flags() & FLAG_BRANCH_TRUE) != 0) 163 print(", branch-true"); 164 if ((e.flags() & FLAG_BRANCH_FALSE) != 0) 165 print(", branch-false"); 166 println(); 167 } 168 indent(-1); 169 } 170 case CodeAttribute attr -> codeWriter.write(attr); 171 case CompilationIDAttribute attr -> 172 constantWriter.write(attr.compilationId().index()); 173 case ConstantValueAttribute attr -> { 174 print("ConstantValue: "); 175 constantWriter.write(attr.constant().index()); 176 println(); 177 } 178 case DeprecatedAttribute attr -> println("Deprecated: true"); 179 case EnclosingMethodAttribute attr -> { 180 print("EnclosingMethod: #" + attr.enclosingClass().index() + ".#" 181 + attr.enclosingMethod().map(PoolEntry::index).orElse(0)); 182 tab(); 183 print("// " + getJavaName(attr.enclosingClass().asInternalName())); 184 if (attr.enclosingMethod().isPresent()) 185 print("." + attr.enclosingMethod().get().name().stringValue()); 186 println(); 187 } 188 case ExceptionsAttribute attr -> { 189 println("Exceptions:"); 190 indent(+1); 191 print("throws "); 192 var exc = attr.exceptions(); 193 for (int i = 0; i < exc.size(); i++) { 194 if (i > 0) 195 print(", "); 196 print(getJavaName(exc.get(i).asInternalName())); 197 } 198 println(); 199 indent(-1); 200 } 201 case InnerClassesAttribute attr -> { 202 boolean first = true; 203 for (var info : attr.classes()) { 204 //access 205 int access_flags = info.flagsMask(); 206 if (options.checkAccess(access_flags)) { 207 if (first) { 208 println("InnerClasses:"); 209 indent(+1); 210 first = false; 211 } 212 for (var flag : maskToAccessFlagsReportUnknown(access_flags, AccessFlag.Location.INNER_CLASS)) { 213 if (flag.sourceModifier() && (flag != AccessFlag.ABSTRACT 214 || !info.has(AccessFlag.INTERFACE))) { 215 print(Modifier.toString(flag.mask()) + " "); 216 } 217 } 218 if (info.innerName().isPresent()) { 219 print("#" + info.innerName().get().index() + "= "); 220 } 221 print("#" + info.innerClass().index()); 222 if (info.outerClass().isPresent()) { 223 print(" of #" + info.outerClass().get().index()); 224 } 225 print(";"); 226 tab(); 227 print("// "); 228 if (info.innerName().isPresent()) { 229 print(info.innerName().get().stringValue() + "="); 230 } 231 constantWriter.write(info.innerClass().index()); 232 if (info.outerClass().isPresent()) { 233 print(" of "); 234 constantWriter.write(info.outerClass().get().index()); 235 } 236 println(); 237 } 238 } 239 if (!first) 240 indent(-1); 241 } 242 case LineNumberTableAttribute attr -> { 243 println("LineNumberTable:"); 244 indent(+1); 245 for (var entry: attr.lineNumbers()) { 246 println("line " + entry.lineNumber() + ": " + entry.startPc()); 247 } 248 indent(-1); 249 } 250 case LocalVariableTableAttribute attr -> { 251 println("LocalVariableTable:"); 252 indent(+1); 253 println("Start Length Slot Name Signature"); 254 for (var entry : attr.localVariables()) { 255 println(String.format("%5d %7d %5d %5s %s", 256 entry.startPc(), entry.length(), entry.slot(), 257 constantWriter.stringValue(entry.name()), 258 constantWriter.stringValue(entry.type()))); 259 } 260 indent(-1); 261 } 262 case LocalVariableTypeTableAttribute attr -> { 263 println("LocalVariableTypeTable:"); 264 indent(+1); 265 println("Start Length Slot Name Signature"); 266 for (var entry : attr.localVariableTypes()) { 267 println(String.format("%5d %7d %5d %5s %s", 268 entry.startPc(), entry.length(), entry.slot(), 269 constantWriter.stringValue(entry.name()), 270 constantWriter.stringValue(entry.signature()))); 271 } 272 indent(-1); 273 } 274 case NestHostAttribute attr -> { 275 print("NestHost: "); 276 constantWriter.write(attr.nestHost().index()); 277 println(); 278 } 279 case MethodParametersAttribute attr -> { 280 final String header = String.format(format, "Name", "Flags"); 281 println("MethodParameters:"); 282 indent(+1); 283 println(header); 284 for (var entry : attr.parameters()) { 285 String namestr = 286 entry.name().isPresent() ? 287 constantWriter.stringValue(entry.name().get()) : "<no name>"; 288 String flagstr = 289 (entry.has(AccessFlag.FINAL) ? "final " : "") + 290 (entry.has(AccessFlag.MANDATED) ? "mandated " : "") + 291 (entry.has(AccessFlag.SYNTHETIC) ? "synthetic" : ""); 292 println(String.format(format, namestr, flagstr)); 293 } 294 indent(-1); 295 } 296 case ModuleAttribute attr -> { 297 println("Module:"); 298 indent(+1); 299 300 print("#" + attr.moduleName().index()); 301 print(","); 302 print(String.format("%x", attr.moduleFlagsMask())); 303 tab(); 304 print("// " + constantWriter.stringValue(attr.moduleName())); 305 if (attr.has(AccessFlag.OPEN)) 306 print(" ACC_OPEN"); 307 if (attr.has(AccessFlag.MANDATED)) 308 print(" ACC_MANDATED"); 309 if (attr.has(AccessFlag.SYNTHETIC)) 310 print(" ACC_SYNTHETIC"); 311 println(); 312 var ver = attr.moduleVersion(); 313 print("#" + ver.map(Utf8Entry::index).orElse(0)); 314 if (ver.isPresent()) { 315 tab(); 316 print("// " + constantWriter.stringValue(ver.get())); 317 } 318 println(); 319 { 320 var entries = attr.requires(); 321 print(entries.size()); 322 tab(); 323 println("// " + "requires"); 324 indent(+1); 325 for (var e: entries) { 326 print("#" + e.requires().index() + "," 327 + String.format("%x", e.requiresFlagsMask())); 328 tab(); 329 print("// " + constantWriter.stringValue(e.requires())); 330 if (e.has(AccessFlag.TRANSITIVE)) 331 print(" ACC_TRANSITIVE"); 332 if (e.has(AccessFlag.STATIC_PHASE)) 333 print(" ACC_STATIC_PHASE"); 334 if (e.has(AccessFlag.SYNTHETIC)) 335 print(" ACC_SYNTHETIC"); 336 if (e.has(AccessFlag.MANDATED)) 337 print(" ACC_MANDATED"); 338 println(); 339 var reqVer = e.requiresVersion(); 340 print("#" + reqVer.map(Utf8Entry::index).orElse(0)); 341 if (reqVer.isPresent()) { 342 tab(); 343 print("// " + constantWriter.stringValue(reqVer.get())); 344 } 345 println(); 346 } 347 indent(-1); 348 } 349 { 350 var entries = attr.exports(); 351 print(entries.size()); 352 tab(); 353 println("// exports"); 354 indent(+1); 355 for (var e: entries) { 356 printExportOpenEntry(e.exportedPackage().index(), 357 e.exportsFlagsMask(), e.exportsTo()); 358 } 359 indent(-1); 360 } 361 { 362 var entries = attr.opens(); 363 print(entries.size()); 364 tab(); 365 println("// opens"); 366 indent(+1); 367 for (var e: entries) { 368 printExportOpenEntry(e.openedPackage().index(), 369 e.opensFlagsMask(), e.opensTo()); 370 } 371 indent(-1); 372 } 373 { 374 var entries = attr.uses(); 375 print(entries.size()); 376 tab(); 377 println("// " + "uses"); 378 indent(+1); 379 for (var e: entries) { 380 print("#" + e.index()); 381 tab(); 382 println("// " + constantWriter.stringValue(e)); 383 } 384 indent(-1); 385 } 386 { 387 var entries = attr.provides(); 388 print(entries.size()); 389 tab(); 390 println("// " + "provides"); 391 indent(+1); 392 for (var e: entries) { 393 print("#" + e.provides().index()); 394 tab(); 395 print("// "); 396 print(constantWriter.stringValue(e.provides())); 397 println(" with ... " + e.providesWith().size()); 398 indent(+1); 399 for (var with : e.providesWith()) { 400 print("#" + with.index()); 401 tab(); 402 println("// ... with " + constantWriter.stringValue(with)); 403 } 404 indent(-1); 405 } 406 indent(-1); 407 } 408 indent(-1); 409 } 410 case ModuleHashesAttribute attr -> { 411 println("ModuleHashes:"); 412 indent(+1); 413 print("algorithm: #" + attr.algorithm().index()); 414 tab(); 415 println("// " + attr.algorithm().stringValue()); 416 print(attr.hashes().size()); 417 tab(); 418 println("// hashes"); 419 for (var e : attr.hashes()) { 420 print("#" + e.moduleName().index()); 421 tab(); 422 println("// " + e.moduleName().name().stringValue()); 423 println("hash_length: " + e.hash().length); 424 println("hash: [" + toHex(e.hash()) + "]"); 425 } 426 indent(-1); 427 } 428 case ModuleMainClassAttribute attr -> { 429 print("ModuleMainClass: #" + attr.mainClass().index()); 430 tab(); 431 print("// " + getJavaName(attr.mainClass().asInternalName())); 432 println(); 433 } 434 case ModulePackagesAttribute attr -> { 435 println("ModulePackages: "); 436 indent(+1); 437 for (var p : attr.packages()) { 438 print("#" + p.index()); 439 tab(); 440 println("// " + getJavaName(p.name().stringValue())); 441 } 442 indent(-1); 443 } 444 case ModuleResolutionAttribute attr -> { 445 println("ModuleResolution:"); 446 indent(+1); 447 print(String.format("%x", attr.resolutionFlags())); 448 tab(); 449 print("// "); 450 int flags = attr.resolutionFlags(); 451 if ((flags & DO_NOT_RESOLVE_BY_DEFAULT) != 0) 452 print(" DO_NOT_RESOLVE_BY_DEFAULT"); 453 if ((flags & WARN_DEPRECATED) != 0) 454 print(" WARN_DEPRECATED"); 455 if ((flags & WARN_DEPRECATED_FOR_REMOVAL) != 0) 456 print(" WARN_DEPRECATED_FOR_REMOVAL"); 457 if ((flags & WARN_INCUBATING) != 0) 458 print(" WARN_INCUBATING"); 459 println(); 460 indent(-1); 461 } 462 case ModuleTargetAttribute attr -> { 463 println("ModuleTarget:"); 464 indent(+1); 465 print("target_platform: #" + attr.targetPlatform().index()); 466 tab(); 467 println("// " + attr.targetPlatform().stringValue()); 468 indent(-1); 469 } 470 case NestMembersAttribute attr -> { 471 println("NestMembers:"); 472 indent(+1); 473 for (var m : attr.nestMembers()) { 474 println(constantWriter.stringValue(m)); 475 } 476 indent(-1); 477 } 478 case RecordAttribute attr -> { 479 println("Record:"); 480 indent(+1); 481 for (var componentInfo : attr.components()) { 482 var sigAttr = componentInfo.findAttribute(Attributes.signature()); 483 print(getJavaName( 484 new ClassWriter.SignaturePrinter(options.verbose).print( 485 sigAttr.map(SignatureAttribute::asTypeSignature) 486 .orElse(Signature.of( 487 componentInfo.descriptorSymbol()))))); 488 print(" "); 489 print(componentInfo.name().stringValue()); 490 print(";"); 491 println(); 492 indent(+1); 493 if (options.showDescriptors) { 494 println("descriptor: " + componentInfo.descriptor().stringValue()); 495 } 496 if (options.showAllAttrs) { 497 write(componentInfo.attributes()); 498 println(); 499 } 500 indent(-1); 501 } 502 indent(-1); 503 } 504 case RuntimeVisibleAnnotationsAttribute attr -> 505 printAnnotations("RuntimeVisibleAnnotations:", attr.annotations()); 506 case RuntimeInvisibleAnnotationsAttribute attr -> 507 printAnnotations("RuntimeInvisibleAnnotations:", attr.annotations()); 508 case RuntimeVisibleTypeAnnotationsAttribute attr -> 509 printTypeAnnotations("RuntimeVisibleTypeAnnotations:", 510 attr.annotations(), lr); 511 case RuntimeInvisibleTypeAnnotationsAttribute attr -> 512 printTypeAnnotations("RuntimeInvisibleTypeAnnotations:", 513 attr.annotations(), lr); 514 case RuntimeVisibleParameterAnnotationsAttribute attr -> 515 printParameterAnnotations("RuntimeVisibleParameterAnnotations:", 516 attr.parameterAnnotations()); 517 case RuntimeInvisibleParameterAnnotationsAttribute attr -> 518 printParameterAnnotations("RuntimeInvisibleParameterAnnotations:", 519 attr.parameterAnnotations()); 520 case PermittedSubclassesAttribute attr -> { 521 println("PermittedSubclasses:"); 522 indent(+1); 523 for (var sc : attr.permittedSubclasses()) { 524 println(constantWriter.stringValue(sc)); 525 } 526 indent(-1); 527 } 528 case SignatureAttribute attr -> { 529 print("Signature: #" + attr.signature().index()); 530 tab(); 531 println("// " + attr.signature().stringValue()); 532 } 533 case SourceDebugExtensionAttribute attr -> { 534 println("SourceDebugExtension:"); 535 indent(+1); 536 for (String s: new String(attr.contents(), StandardCharsets.UTF_8) 537 .split("[\r\n]+")) { 538 println(s); 539 } 540 indent(-1); 541 } 542 case SourceFileAttribute attr -> 543 println("SourceFile: \"" + attr.sourceFile().stringValue() + "\""); 544 case SourceIDAttribute attr -> 545 constantWriter.write(attr.sourceId().index()); 546 case StackMapTableAttribute attr -> { 547 var entries = attr.entries(); 548 println("StackMapTable: number_of_entries = " + entries.size()); 549 indent(+1); 550 int lastOffset = -1; 551 for (var frame : entries) { 552 int frameType = frame.frameType(); 553 if (frameType < 64) { 554 printHeader(frameType, "/* same */"); 555 } else if (frameType < 128) { 556 printHeader(frameType, "/* same_locals_1_stack_item */"); 557 indent(+1); 558 printMap("stack", frame.stack(), lr); 559 indent(-1); 560 } else { 561 int offsetDelta = lr.labelToBci(frame.target()) - lastOffset - 1; 562 switch (frameType) { 563 case 247 -> { 564 printHeader(frameType, "/* same_locals_1_stack_item_frame_extended */"); 565 indent(+1); 566 println("offset_delta = " + offsetDelta); 567 printMap("stack", frame.stack(), lr); 568 indent(-1); 569 } 570 case 248, 249, 250 -> { 571 printHeader(frameType, "/* chop */"); 572 indent(+1); 573 println("offset_delta = " + offsetDelta); 574 indent(-1); 575 } 576 case 251 -> { 577 printHeader(frameType, "/* same_frame_extended */"); 578 indent(+1); 579 println("offset_delta = " + offsetDelta); 580 indent(-1); 581 } 582 case 252, 253, 254 -> { 583 printHeader(frameType, "/* append */"); 584 indent(+1); 585 println("offset_delta = " + offsetDelta); 586 var locals = frame.locals(); 587 printMap("locals", locals.subList(locals.size() 588 - frameType + 251, locals.size()), lr); 589 indent(-1); 590 } 591 case 255 -> { 592 printHeader(frameType, "/* full_frame */"); 593 indent(+1); 594 println("offset_delta = " + offsetDelta); 595 printMap("locals", frame.locals(), lr); 596 printMap("stack", frame.stack(), lr); 597 indent(-1); 598 } 599 } 600 } 601 lastOffset = lr.labelToBci(frame.target()); 602 } 603 indent(-1); 604 } 605 case SyntheticAttribute attr -> 606 println("Synthetic: true"); 607 default -> {} 608 } 609 } 610 611 //ToDo move somewhere to Bytecode API 612 public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001; 613 public static final int WARN_DEPRECATED = 0x0002; 614 public static final int WARN_DEPRECATED_FOR_REMOVAL = 0x0004; 615 public static final int WARN_INCUBATING = 0x0008; 616 617 private static final String format = "%-31s%s"; 618 619 protected void printExportOpenEntry(int index, int flags, List<ModuleEntry> to_index) { 620 print("#" + index + "," + String.format("%x", flags)); 621 tab(); 622 print("// "); 623 print(constantWriter.stringValue(index)); 624 if ((flags & ACC_MANDATED) != 0) 625 print(" ACC_MANDATED"); 626 if ((flags & ACC_SYNTHETIC) != 0) 627 print(" ACC_SYNTHETIC"); 628 if (to_index.size() == 0) { 629 println(); 630 } else { 631 println(" to ... " + to_index.size()); 632 indent(+1); 633 for (var to: to_index) { 634 print("#" + to.index()); 635 tab(); 636 println("// ... to " + constantWriter.stringValue(to)); 637 } 638 indent(-1); 639 } 640 } 641 642 private void printAnnotations(String message, List<? extends Annotation> anno) { 643 println(message); 644 indent(+1); 645 for (int i = 0; i < anno.size(); i++) { 646 print(i + ": "); 647 annotationWriter.write(anno.get(i)); 648 println(); 649 } 650 indent(-1); 651 } 652 653 private void printTypeAnnotations(String message, 654 List<? extends TypeAnnotation> anno, CodeAttribute lr) { 655 println(message); 656 indent(+1); 657 for (int i = 0; i < anno.size(); i++) { 658 print(i + ": "); 659 annotationWriter.write(anno.get(i), lr); 660 println(); 661 } 662 indent(-1); 663 } 664 665 private void printParameterAnnotations(String message, List<List<Annotation>> paramsAnno) { 666 println(message); 667 indent(+1); 668 for (int param = 0; param < paramsAnno.size(); param++) { 669 println("parameter " + param + ": "); 670 indent(+1); 671 var annos = paramsAnno.get(param); 672 for (int i = 0; i < annos.size(); i++) { 673 print(i + ": "); 674 annotationWriter.write(annos.get(i)); 675 println(); 676 } 677 indent(-1); 678 } 679 indent(-1); 680 } 681 682 void printHeader(int frameType, String extra) { 683 print("frame_type = " + frameType + " "); 684 println(extra); 685 } 686 687 void printMap(String name, List<VerificationTypeInfo> map, CodeAttribute lr) { 688 print(name + " = ["); 689 for (int i = 0; i < map.size(); i++) { 690 var info = map.get(i); 691 switch (info) { 692 case ObjectVerificationTypeInfo obj -> { 693 print(" "); 694 constantWriter.write(obj.className().index()); 695 } 696 case UninitializedVerificationTypeInfo u -> { 697 print(" uninitialized " + lr.labelToBci(u.newTarget())); 698 } 699 case SimpleVerificationTypeInfo s -> 700 print(" " + mapTypeName(s)); 701 } 702 print(i == (map.size() - 1) ? " " : ","); 703 } 704 println("]"); 705 } 706 707 String mapTypeName(SimpleVerificationTypeInfo type) { 708 return switch (type) { 709 case TOP -> "top"; 710 case INTEGER -> "int"; 711 case FLOAT -> "float"; 712 case LONG -> "long"; 713 case DOUBLE -> "double"; 714 case NULL -> "null"; 715 case UNINITIALIZED_THIS -> "this"; 716 }; 717 } 718 719 static String getJavaName(String name) { 720 return name.replace('/', '.'); 721 } 722 723 String toHex(byte b, int w) { 724 return toHex(b & 0xff, w); 725 } 726 727 static String toHex(int i) { 728 return Integer.toString(i, 16).toUpperCase(Locale.US); 729 } 730 731 static String toHex(int i, int w) { 732 String s = Integer.toHexString(i).toUpperCase(Locale.US); 733 while (s.length() < w) 734 s = "0" + s; 735 return s; 736 } 737 738 static String toHex(byte[] ba) { 739 StringBuilder sb = new StringBuilder(ba.length); 740 for (byte b: ba) { 741 sb.append(String.format("%02x", b & 0xff)); 742 } 743 return sb.toString(); 744 } 745 746 private final AnnotationWriter annotationWriter; 747 private final CodeWriter codeWriter; 748 private final ConstantWriter constantWriter; 749 private final Options options; 750 }