Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java
38899 views
/*1* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.javap;2627import com.sun.tools.classfile.ClassFile;28import com.sun.tools.classfile.ConstantPool;29import com.sun.tools.classfile.ConstantPoolException;3031import static com.sun.tools.classfile.ConstantPool.*;3233/*34* Write a constant pool entry.35*36* <p><b>This is NOT part of any supported API.37* If you write code that depends on this, you do so at your own risk.38* This code and its internal interfaces are subject to change or39* deletion without notice.</b>40*/41public class ConstantWriter extends BasicWriter {42public static ConstantWriter instance(Context context) {43ConstantWriter instance = context.get(ConstantWriter.class);44if (instance == null)45instance = new ConstantWriter(context);46return instance;47}4849protected ConstantWriter(Context context) {50super(context);51context.put(ConstantWriter.class, this);52classWriter = ClassWriter.instance(context);53options = Options.instance(context);54}5556protected void writeConstantPool() {57ConstantPool constant_pool = classWriter.getClassFile().constant_pool;58writeConstantPool(constant_pool);59}6061protected void writeConstantPool(ConstantPool constant_pool) {62ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer,Void>() {63public Integer visitClass(CONSTANT_Class_info info, Void p) {64print("#" + info.name_index);65tab();66println("// " + stringValue(info));67return 1;68}6970public Integer visitDouble(CONSTANT_Double_info info, Void p) {71println(stringValue(info));72return 2;73}7475public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {76print("#" + info.class_index + ".#" + info.name_and_type_index);77tab();78println("// " + stringValue(info));79return 1;80}8182public Integer visitFloat(CONSTANT_Float_info info, Void p) {83println(stringValue(info));84return 1;85}8687public Integer visitInteger(CONSTANT_Integer_info info, Void p) {88println(stringValue(info));89return 1;90}9192public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {93print("#" + info.class_index + ".#" + info.name_and_type_index);94tab();95println("// " + stringValue(info));96return 1;97}9899public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {100print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index);101tab();102println("// " + stringValue(info));103return 1;104}105106public Integer visitLong(CONSTANT_Long_info info, Void p) {107println(stringValue(info));108return 2;109}110111public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {112print("#" + info.name_index + ":#" + info.type_index);113tab();114println("// " + stringValue(info));115return 1;116}117118public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {119print("#" + info.class_index + ".#" + info.name_and_type_index);120tab();121println("// " + stringValue(info));122return 1;123}124125public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {126print("#" + info.reference_kind.tag + ":#" + info.reference_index);127tab();128println("// " + stringValue(info));129return 1;130}131132public Integer visitMethodType(CONSTANT_MethodType_info info, Void p) {133print("#" + info.descriptor_index);134tab();135println("// " + stringValue(info));136return 1;137}138139public Integer visitString(CONSTANT_String_info info, Void p) {140print("#" + info.string_index);141tab();142println("// " + stringValue(info));143return 1;144}145146public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {147println(stringValue(info));148return 1;149}150151};152println("Constant pool:");153indent(+1);154int width = String.valueOf(constant_pool.size()).length() + 1;155int cpx = 1;156while (cpx < constant_pool.size()) {157print(String.format("%" + width + "s", ("#" + cpx)));158try {159CPInfo cpInfo = constant_pool.get(cpx);160print(String.format(" = %-18s ", cpTagName(cpInfo)));161cpx += cpInfo.accept(v, null);162} catch (ConstantPool.InvalidIndex ex) {163// should not happen164}165}166indent(-1);167}168169protected void write(int cpx) {170ClassFile classFile = classWriter.getClassFile();171if (cpx == 0) {172print("#0");173return;174}175176CPInfo cpInfo;177try {178cpInfo = classFile.constant_pool.get(cpx);179} catch (ConstantPoolException e) {180print("#" + cpx);181return;182}183184int tag = cpInfo.getTag();185switch (tag) {186case CONSTANT_Methodref:187case CONSTANT_InterfaceMethodref:188case CONSTANT_Fieldref:189// simplify references within this class190CPRefInfo ref = (CPRefInfo) cpInfo;191try {192if (ref.class_index == classFile.this_class)193cpInfo = classFile.constant_pool.get(ref.name_and_type_index);194} catch (ConstantPool.InvalidIndex e) {195// ignore, for now196}197}198print(tagName(tag) + " " + stringValue(cpInfo));199}200201String cpTagName(CPInfo cpInfo) {202String n = cpInfo.getClass().getSimpleName();203return n.replace("CONSTANT_", "").replace("_info", "");204}205206String tagName(int tag) {207switch (tag) {208case CONSTANT_Utf8:209return "Utf8";210case CONSTANT_Integer:211return "int";212case CONSTANT_Float:213return "float";214case CONSTANT_Long:215return "long";216case CONSTANT_Double:217return "double";218case CONSTANT_Class:219return "class";220case CONSTANT_String:221return "String";222case CONSTANT_Fieldref:223return "Field";224case CONSTANT_MethodHandle:225return "MethodHandle";226case CONSTANT_MethodType:227return "MethodType";228case CONSTANT_Methodref:229return "Method";230case CONSTANT_InterfaceMethodref:231return "InterfaceMethod";232case CONSTANT_InvokeDynamic:233return "InvokeDynamic";234case CONSTANT_NameAndType:235return "NameAndType";236default:237return "(unknown tag " + tag + ")";238}239}240241String stringValue(int constant_pool_index) {242ClassFile classFile = classWriter.getClassFile();243try {244return stringValue(classFile.constant_pool.get(constant_pool_index));245} catch (ConstantPool.InvalidIndex e) {246return report(e);247}248}249250String stringValue(CPInfo cpInfo) {251return stringValueVisitor.visit(cpInfo);252}253254StringValueVisitor stringValueVisitor = new StringValueVisitor();255256private class StringValueVisitor implements ConstantPool.Visitor<String, Void> {257public String visit(CPInfo info) {258return info.accept(this, null);259}260261public String visitClass(CONSTANT_Class_info info, Void p) {262return getCheckedName(info);263}264265String getCheckedName(CONSTANT_Class_info info) {266try {267return checkName(info.getName());268} catch (ConstantPoolException e) {269return report(e);270}271}272273public String visitDouble(CONSTANT_Double_info info, Void p) {274return info.value + "d";275}276277public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {278return visitRef(info, p);279}280281public String visitFloat(CONSTANT_Float_info info, Void p) {282return info.value + "f";283}284285public String visitInteger(CONSTANT_Integer_info info, Void p) {286return String.valueOf(info.value);287}288289public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {290return visitRef(info, p);291}292293public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {294try {295String callee = stringValue(info.getNameAndTypeInfo());296return "#" + info.bootstrap_method_attr_index + ":" + callee;297} catch (ConstantPoolException e) {298return report(e);299}300}301302public String visitLong(CONSTANT_Long_info info, Void p) {303return info.value + "l";304}305306public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {307return getCheckedName(info) + ":" + getType(info);308}309310String getCheckedName(CONSTANT_NameAndType_info info) {311try {312return checkName(info.getName());313} catch (ConstantPoolException e) {314return report(e);315}316}317318String getType(CONSTANT_NameAndType_info info) {319try {320return info.getType();321} catch (ConstantPoolException e) {322return report(e);323}324}325326public String visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {327try {328return info.reference_kind.name + " " + stringValue(info.getCPRefInfo());329} catch (ConstantPoolException e) {330return report(e);331}332}333334public String visitMethodType(CONSTANT_MethodType_info info, Void p) {335try {336return info.getType();337} catch (ConstantPoolException e) {338return report(e);339}340}341342public String visitMethodref(CONSTANT_Methodref_info info, Void p) {343return visitRef(info, p);344}345346public String visitString(CONSTANT_String_info info, Void p) {347try {348ClassFile classFile = classWriter.getClassFile();349int string_index = info.string_index;350return stringValue(classFile.constant_pool.getUTF8Info(string_index));351} catch (ConstantPoolException e) {352return report(e);353}354}355356public String visitUtf8(CONSTANT_Utf8_info info, Void p) {357String s = info.value;358StringBuilder sb = new StringBuilder();359for (int i = 0; i < s.length(); i++) {360char c = s.charAt(i);361switch (c) {362case '\t':363sb.append('\\').append('t');364break;365case '\n':366sb.append('\\').append('n');367break;368case '\r':369sb.append('\\').append('r');370break;371case '\"':372sb.append('\\').append('\"');373break;374default:375sb.append(c);376}377}378return sb.toString();379}380381String visitRef(CPRefInfo info, Void p) {382String cn = getCheckedClassName(info);383String nat;384try {385nat = stringValue(info.getNameAndTypeInfo());386} catch (ConstantPoolException e) {387nat = report(e);388}389return cn + "." + nat;390}391392String getCheckedClassName(CPRefInfo info) {393try {394return checkName(info.getClassName());395} catch (ConstantPoolException e) {396return report(e);397}398}399}400401/* If name is a valid binary name, return it; otherwise quote it. */402private static String checkName(String name) {403if (name == null)404return "null";405406int len = name.length();407if (len == 0)408return "\"\"";409410int cc = '/';411int cp;412for (int k = 0; k < len; k += Character.charCount(cp)) {413cp = name.codePointAt(k);414if ((cc == '/' && !Character.isJavaIdentifierStart(cp))415|| (cp != '/' && !Character.isJavaIdentifierPart(cp))) {416return "\"" + addEscapes(name) + "\"";417}418cc = cp;419}420421return name;422}423424/* If name requires escapes, put them in, so it can be a string body. */425private static String addEscapes(String name) {426String esc = "\\\"\n\t";427String rep = "\\\"nt";428StringBuilder buf = null;429int nextk = 0;430int len = name.length();431for (int k = 0; k < len; k++) {432char cp = name.charAt(k);433int n = esc.indexOf(cp);434if (n >= 0) {435if (buf == null)436buf = new StringBuilder(len * 2);437if (nextk < k)438buf.append(name, nextk, k);439buf.append('\\');440buf.append(rep.charAt(n));441nextk = k+1;442}443}444if (buf == null)445return name;446if (nextk < len)447buf.append(name, nextk, len);448return buf.toString();449}450451private ClassWriter classWriter;452private Options options;453}454455456