Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java
58461 views
/*1* Copyright (c) 2007, 2020, 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<>() {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 visitDynamicConstant(CONSTANT_Dynamic_info info, Void p) {107print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index);108tab();109println("// " + stringValue(info));110return 1;111}112113public Integer visitLong(CONSTANT_Long_info info, Void p) {114println(stringValue(info));115return 2;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 visitModule(CONSTANT_Module_info info, Void p) {140print("#" + info.name_index);141tab();142println("// " + stringValue(info));143return 1;144}145146public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {147print("#" + info.name_index + ":#" + info.type_index);148tab();149println("// " + stringValue(info));150return 1;151}152153public Integer visitPackage(CONSTANT_Package_info info, Void p) {154print("#" + info.name_index);155tab();156println("// " + stringValue(info));157return 1;158}159160public Integer visitString(CONSTANT_String_info info, Void p) {161print("#" + info.string_index);162tab();163println("// " + stringValue(info));164return 1;165}166167public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {168println(stringValue(info));169return 1;170}171172};173println("Constant pool:");174indent(+1);175int width = String.valueOf(constant_pool.size()).length() + 1;176int cpx = 1;177while (cpx < constant_pool.size()) {178print(String.format("%" + width + "s", ("#" + cpx)));179try {180CPInfo cpInfo = constant_pool.get(cpx);181print(String.format(" = %-18s ", cpTagName(cpInfo)));182cpx += cpInfo.accept(v, null);183} catch (ConstantPool.InvalidIndex ex) {184// should not happen185}186}187indent(-1);188}189190protected void write(int cpx) {191ClassFile classFile = classWriter.getClassFile();192if (cpx == 0) {193print("#0");194return;195}196197CPInfo cpInfo;198try {199cpInfo = classFile.constant_pool.get(cpx);200} catch (ConstantPoolException e) {201print("#" + cpx);202return;203}204205int tag = cpInfo.getTag();206switch (tag) {207case CONSTANT_Methodref:208case CONSTANT_InterfaceMethodref:209case CONSTANT_Fieldref:210// simplify references within this class211CPRefInfo ref = (CPRefInfo) cpInfo;212try {213if (ref.class_index == classFile.this_class)214cpInfo = classFile.constant_pool.get(ref.name_and_type_index);215} catch (ConstantPool.InvalidIndex e) {216// ignore, for now217}218}219print(tagName(tag) + " " + stringValue(cpInfo));220}221222String cpTagName(CPInfo cpInfo) {223String n = cpInfo.getClass().getSimpleName();224return n.replace("CONSTANT_", "").replace("_info", "");225}226227String tagName(int tag) {228switch (tag) {229case CONSTANT_Utf8:230return "Utf8";231case CONSTANT_Integer:232return "int";233case CONSTANT_Float:234return "float";235case CONSTANT_Long:236return "long";237case CONSTANT_Double:238return "double";239case CONSTANT_Class:240return "class";241case CONSTANT_String:242return "String";243case CONSTANT_Fieldref:244return "Field";245case CONSTANT_MethodHandle:246return "MethodHandle";247case CONSTANT_MethodType:248return "MethodType";249case CONSTANT_Methodref:250return "Method";251case CONSTANT_InterfaceMethodref:252return "InterfaceMethod";253case CONSTANT_InvokeDynamic:254return "InvokeDynamic";255case CONSTANT_Dynamic:256return "Dynamic";257case CONSTANT_NameAndType:258return "NameAndType";259default:260return "(unknown tag " + tag + ")";261}262}263264String booleanValue(int constant_pool_index) {265ClassFile classFile = classWriter.getClassFile();266try {267CPInfo info = classFile.constant_pool.get(constant_pool_index);268if (info instanceof CONSTANT_Integer_info) {269int value = ((CONSTANT_Integer_info) info).value;270switch (value) {271case 0: return "false";272case 1: return "true";273}274}275return "#" + constant_pool_index;276} catch (ConstantPool.InvalidIndex e) {277return report(e);278}279}280281String charValue(int constant_pool_index) {282ClassFile classFile = classWriter.getClassFile();283try {284CPInfo info = classFile.constant_pool.get(constant_pool_index);285if (info instanceof CONSTANT_Integer_info) {286int value = ((CONSTANT_Integer_info) info).value;287return String.valueOf((char) value);288} else {289return "#" + constant_pool_index;290}291} catch (ConstantPool.InvalidIndex e) {292return report(e);293}294}295296String stringValue(int constant_pool_index) {297ClassFile classFile = classWriter.getClassFile();298try {299return stringValue(classFile.constant_pool.get(constant_pool_index));300} catch (ConstantPool.InvalidIndex e) {301return report(e);302}303}304305String stringValue(CPInfo cpInfo) {306return stringValueVisitor.visit(cpInfo);307}308309StringValueVisitor stringValueVisitor = new StringValueVisitor();310311private class StringValueVisitor implements ConstantPool.Visitor<String, Void> {312public String visit(CPInfo info) {313return info.accept(this, null);314}315316public String visitClass(CONSTANT_Class_info info, Void p) {317return getCheckedName(info);318}319320String getCheckedName(CONSTANT_Class_info info) {321try {322return checkName(info.getName());323} catch (ConstantPoolException e) {324return report(e);325}326}327328public String visitDouble(CONSTANT_Double_info info, Void p) {329return info.value + "d";330}331332public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {333return visitRef(info, p);334}335336public String visitFloat(CONSTANT_Float_info info, Void p) {337return info.value + "f";338}339340public String visitInteger(CONSTANT_Integer_info info, Void p) {341return String.valueOf(info.value);342}343344public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {345return visitRef(info, p);346}347348public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {349try {350String callee = stringValue(info.getNameAndTypeInfo());351return "#" + info.bootstrap_method_attr_index + ":" + callee;352} catch (ConstantPoolException e) {353return report(e);354}355}356357public String visitDynamicConstant(CONSTANT_Dynamic_info info, Void p) {358try {359String callee = stringValue(info.getNameAndTypeInfo());360return "#" + info.bootstrap_method_attr_index + ":" + callee;361} catch (ConstantPoolException e) {362return report(e);363}364}365366public String visitLong(CONSTANT_Long_info info, Void p) {367return info.value + "l";368}369370public String visitModule(CONSTANT_Module_info info, Void p) {371try {372return checkName(info.getName());373} catch (ConstantPoolException e) {374return report(e);375}376}377378public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {379return getCheckedName(info) + ":" + getType(info);380}381382String getCheckedName(CONSTANT_NameAndType_info info) {383try {384return checkName(info.getName());385} catch (ConstantPoolException e) {386return report(e);387}388}389390public String visitPackage(CONSTANT_Package_info info, Void p) {391try {392return checkName(info.getName());393} catch (ConstantPoolException e) {394return report(e);395}396}397398String getType(CONSTANT_NameAndType_info info) {399try {400return info.getType();401} catch (ConstantPoolException e) {402return report(e);403}404}405406public String visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {407try {408return info.reference_kind + " " + stringValue(info.getCPRefInfo());409} catch (ConstantPoolException e) {410return report(e);411}412}413414public String visitMethodType(CONSTANT_MethodType_info info, Void p) {415try {416return info.getType();417} catch (ConstantPoolException e) {418return report(e);419}420}421422public String visitMethodref(CONSTANT_Methodref_info info, Void p) {423return visitRef(info, p);424}425426public String visitString(CONSTANT_String_info info, Void p) {427try {428ClassFile classFile = classWriter.getClassFile();429int string_index = info.string_index;430return stringValue(classFile.constant_pool.getUTF8Info(string_index));431} catch (ConstantPoolException e) {432return report(e);433}434}435436public String visitUtf8(CONSTANT_Utf8_info info, Void p) {437String s = info.value;438StringBuilder sb = new StringBuilder();439for (int i = 0; i < s.length(); i++) {440char c = s.charAt(i);441switch (c) {442case '\t':443sb.append('\\').append('t');444break;445case '\n':446sb.append('\\').append('n');447break;448case '\r':449sb.append('\\').append('r');450break;451case '\b':452sb.append('\\').append('b');453break;454case '\f':455sb.append('\\').append('f');456break;457case '\"':458sb.append('\\').append('\"');459break;460case '\'':461sb.append('\\').append('\'');462break;463case '\\':464sb.append('\\').append('\\');465break;466default:467if (Character.isISOControl(c)) {468sb.append(String.format("\\u%04x", (int) c));469break;470}471sb.append(c);472}473}474return sb.toString();475}476477String visitRef(CPRefInfo info, Void p) {478String cn = getCheckedClassName(info);479String nat;480try {481nat = stringValue(info.getNameAndTypeInfo());482} catch (ConstantPoolException e) {483nat = report(e);484}485return cn + "." + nat;486}487488String getCheckedClassName(CPRefInfo info) {489try {490return checkName(info.getClassName());491} catch (ConstantPoolException e) {492return report(e);493}494}495}496497/* If name is a valid binary name, return it; otherwise quote it. */498private static String checkName(String name) {499if (name == null)500return "null";501502int len = name.length();503if (len == 0)504return "\"\"";505506int cc = '/';507int cp;508for (int k = 0; k < len; k += Character.charCount(cp)) {509cp = name.codePointAt(k);510if ((cc == '/' && !Character.isJavaIdentifierStart(cp))511|| (cp != '/' && !Character.isJavaIdentifierPart(cp))) {512return "\"" + addEscapes(name) + "\"";513}514cc = cp;515}516517return name;518}519520/* If name requires escapes, put them in, so it can be a string body. */521private static String addEscapes(String name) {522String esc = "\\\"\n\t";523String rep = "\\\"nt";524StringBuilder buf = null;525int nextk = 0;526int len = name.length();527for (int k = 0; k < len; k++) {528char cp = name.charAt(k);529int n = esc.indexOf(cp);530if (n >= 0) {531if (buf == null)532buf = new StringBuilder(len * 2);533if (nextk < k)534buf.append(name, nextk, k);535buf.append('\\');536buf.append(rep.charAt(n));537nextk = k+1;538}539}540if (buf == null)541return name;542if (nextk < len)543buf.append(name, nextk, len);544return buf.toString();545}546547private final ClassWriter classWriter;548private final Options options;549}550551552