Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.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 java.io.EOFException;28import java.io.FileNotFoundException;29import java.io.FilterInputStream;30import java.io.InputStream;31import java.io.IOException;32import java.io.OutputStream;33import java.io.PrintWriter;34import java.io.Reader;35import java.io.StringWriter;36import java.io.Writer;37import java.net.URI;38import java.net.URISyntaxException;39import java.net.URL;40import java.net.URLConnection;41import java.nio.file.NoSuchFileException;42import java.security.DigestInputStream;43import java.security.MessageDigest;44import java.security.NoSuchAlgorithmException;45import java.text.MessageFormat;46import java.util.ArrayList;47import java.util.Arrays;48import java.util.EnumSet;49import java.util.HashMap;50import java.util.Iterator;51import java.util.List;52import java.util.Locale;53import java.util.Map;54import java.util.MissingResourceException;55import java.util.Objects;56import java.util.ResourceBundle;57import java.util.Set;5859import javax.lang.model.element.Modifier;60import javax.lang.model.element.NestingKind;61import javax.tools.Diagnostic;62import javax.tools.DiagnosticListener;63import javax.tools.JavaFileManager;64import javax.tools.JavaFileManager.Location;65import javax.tools.JavaFileObject;66import javax.tools.StandardJavaFileManager;67import javax.tools.StandardLocation;6869import com.sun.tools.classfile.*;7071/**72* "Main" class for javap, normally accessed from the command line73* via Main, or from JSR199 via DisassemblerTool.74*75* <p><b>This is NOT part of any supported API.76* If you write code that depends on this, you do so at your own risk.77* This code and its internal interfaces are subject to change or78* deletion without notice.</b>79*/80public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {81public class BadArgs extends Exception {82static final long serialVersionUID = 8765093759964640721L;83BadArgs(String key, Object... args) {84super(JavapTask.this.getMessage(key, args));85this.key = key;86this.args = args;87}8889BadArgs showUsage(boolean b) {90showUsage = b;91return this;92}9394final String key;95final Object[] args;96boolean showUsage;97}9899static abstract class Option {100Option(boolean hasArg, String... aliases) {101this.hasArg = hasArg;102this.aliases = aliases;103}104105boolean matches(String opt) {106for (String a: aliases) {107if (a.equals(opt))108return true;109}110return false;111}112113boolean ignoreRest() {114return false;115}116117abstract void process(JavapTask task, String opt, String arg) throws BadArgs;118119final boolean hasArg;120final String[] aliases;121}122123static final Option[] recognizedOptions = {124125new Option(false, "-help", "--help", "-?", "-h") {126@Override127void process(JavapTask task, String opt, String arg) {128task.options.help = true;129}130},131132new Option(false, "-version") {133@Override134void process(JavapTask task, String opt, String arg) {135task.options.version = true;136}137},138139new Option(false, "-fullversion") {140@Override141void process(JavapTask task, String opt, String arg) {142task.options.fullVersion = true;143}144},145146new Option(false, "-v", "-verbose", "-all") {147@Override148void process(JavapTask task, String opt, String arg) {149task.options.verbose = true;150task.options.showDescriptors = true;151task.options.showFlags = true;152task.options.showAllAttrs = true;153}154},155156new Option(false, "-l") {157@Override158void process(JavapTask task, String opt, String arg) {159task.options.showLineAndLocalVariableTables = true;160}161},162163new Option(false, "-public") {164@Override165void process(JavapTask task, String opt, String arg) {166task.options.accessOptions.add(opt);167task.options.showAccess = AccessFlags.ACC_PUBLIC;168}169},170171new Option(false, "-protected") {172@Override173void process(JavapTask task, String opt, String arg) {174task.options.accessOptions.add(opt);175task.options.showAccess = AccessFlags.ACC_PROTECTED;176}177},178179new Option(false, "-package") {180@Override181void process(JavapTask task, String opt, String arg) {182task.options.accessOptions.add(opt);183task.options.showAccess = 0;184}185},186187new Option(false, "-p", "-private") {188@Override189void process(JavapTask task, String opt, String arg) {190if (!task.options.accessOptions.contains("-p") &&191!task.options.accessOptions.contains("-private")) {192task.options.accessOptions.add(opt);193}194task.options.showAccess = AccessFlags.ACC_PRIVATE;195}196},197198new Option(false, "-c") {199@Override200void process(JavapTask task, String opt, String arg) {201task.options.showDisassembled = true;202}203},204205new Option(false, "-s") {206@Override207void process(JavapTask task, String opt, String arg) {208task.options.showDescriptors = true;209}210},211212new Option(false, "-sysinfo") {213@Override214void process(JavapTask task, String opt, String arg) {215task.options.sysInfo = true;216}217},218219new Option(false, "-XDdetails") {220@Override221void process(JavapTask task, String opt, String arg) {222task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);223}224225},226227new Option(false, "-XDdetails:") {228@Override229boolean matches(String opt) {230int sep = opt.indexOf(":");231return sep != -1 && super.matches(opt.substring(0, sep + 1));232}233234@Override235void process(JavapTask task, String opt, String arg) throws BadArgs {236int sep = opt.indexOf(":");237for (String v: opt.substring(sep + 1).split("[,: ]+")) {238if (!handleArg(task, v))239throw task.new BadArgs("err.invalid.arg.for.option", v);240}241}242243boolean handleArg(JavapTask task, String arg) {244if (arg.length() == 0)245return true;246247if (arg.equals("all")) {248task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);249return true;250}251252boolean on = true;253if (arg.startsWith("-")) {254on = false;255arg = arg.substring(1);256}257258for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {259if (arg.equalsIgnoreCase(k.option)) {260if (on)261task.options.details.add(k);262else263task.options.details.remove(k);264return true;265}266}267return false;268}269},270271new Option(false, "-constants") {272@Override273void process(JavapTask task, String opt, String arg) {274task.options.showConstants = true;275}276},277278new Option(false, "-XDinner") {279@Override280void process(JavapTask task, String opt, String arg) {281task.options.showInnerClasses = true;282}283},284285new Option(false, "-XDindent:") {286@Override287boolean matches(String opt) {288int sep = opt.indexOf(":");289return sep != -1 && super.matches(opt.substring(0, sep + 1));290}291292@Override293void process(JavapTask task, String opt, String arg) throws BadArgs {294int sep = opt.indexOf(":");295try {296int i = Integer.valueOf(opt.substring(sep + 1));297if (i > 0) // silently ignore invalid values298task.options.indentWidth = i;299} catch (NumberFormatException e) {300}301}302},303304new Option(false, "-XDtab:") {305@Override306boolean matches(String opt) {307int sep = opt.indexOf(":");308return sep != -1 && super.matches(opt.substring(0, sep + 1));309}310311@Override312void process(JavapTask task, String opt, String arg) throws BadArgs {313int sep = opt.indexOf(":");314try {315int i = Integer.valueOf(opt.substring(sep + 1));316if (i > 0) // silently ignore invalid values317task.options.tabColumn = i;318} catch (NumberFormatException e) {319}320}321},322323new Option(true, "--module", "-m") {324@Override325void process(JavapTask task, String opt, String arg) throws BadArgs {326task.options.moduleName = arg;327}328},329330// this option is processed by the launcher, and cannot be used when invoked via331// an API like ToolProvider. It exists here to be documented in the command-line help.332new Option(false, "-J") {333@Override334boolean matches(String opt) {335return opt.startsWith("-J");336}337338@Override339void process(JavapTask task, String opt, String arg) throws BadArgs {340throw task.new BadArgs("err.only.for.launcher");341}342}343344};345346public JavapTask() {347context = new Context();348context.put(Messages.class, this);349options = Options.instance(context);350attributeFactory = new Attribute.Factory();351}352353public JavapTask(Writer out,354JavaFileManager fileManager,355DiagnosticListener<? super JavaFileObject> diagnosticListener) {356this();357this.log = getPrintWriterForWriter(out);358this.fileManager = fileManager;359this.diagnosticListener = diagnosticListener;360}361362public JavapTask(Writer out,363JavaFileManager fileManager,364DiagnosticListener<? super JavaFileObject> diagnosticListener,365Iterable<String> options,366Iterable<String> classes) {367this(out, fileManager, diagnosticListener);368369this.classes = new ArrayList<>();370for (String classname: classes) {371Objects.requireNonNull(classname);372this.classes.add(classname);373}374375try {376if (options != null)377handleOptions(options, false);378} catch (BadArgs e) {379throw new IllegalArgumentException(e.getMessage());380}381}382383public void setLocale(Locale locale) {384if (locale == null)385locale = Locale.getDefault();386task_locale = locale;387}388389public void setLog(Writer log) {390this.log = getPrintWriterForWriter(log);391}392393public void setLog(OutputStream s) {394setLog(getPrintWriterForStream(s));395}396397private static PrintWriter getPrintWriterForStream(OutputStream s) {398return new PrintWriter(s == null ? System.err : s, true);399}400401private static PrintWriter getPrintWriterForWriter(Writer w) {402if (w == null)403return getPrintWriterForStream(null);404else if (w instanceof PrintWriter)405return (PrintWriter) w;406else407return new PrintWriter(w, true);408}409410public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {411diagnosticListener = dl;412}413414public void setDiagnosticListener(OutputStream s) {415setDiagnosticListener(getDiagnosticListenerForStream(s));416}417418private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {419return getDiagnosticListenerForWriter(getPrintWriterForStream(s));420}421422private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {423final PrintWriter pw = getPrintWriterForWriter(w);424return diagnostic -> {425switch (diagnostic.getKind()) {426case ERROR:427pw.print(getMessage("err.prefix"));428break;429case WARNING:430pw.print(getMessage("warn.prefix"));431break;432case NOTE:433pw.print(getMessage("note.prefix"));434break;435}436pw.print(" ");437pw.println(diagnostic.getMessage(null));438};439}440441/** Result codes.442*/443static final int444EXIT_OK = 0, // Compilation completed with no errors.445EXIT_ERROR = 1, // Completed but reported errors.446EXIT_CMDERR = 2, // Bad command-line arguments447EXIT_SYSERR = 3, // System error or resource exhaustion.448EXIT_ABNORMAL = 4; // Compiler terminated abnormally449450int run(String[] args) {451try {452try {453handleOptions(args);454455// the following gives consistent behavior with javac456if (classes == null || classes.size() == 0) {457if (options.help || options.version || options.fullVersion)458return EXIT_OK;459else460return EXIT_CMDERR;461}462463return run();464} finally {465if (defaultFileManager != null) {466try {467defaultFileManager.close();468defaultFileManager = null;469} catch (IOException e) {470throw new InternalError(e);471}472}473}474} catch (BadArgs e) {475reportError(e.key, e.args);476if (e.showUsage) {477printLines(getMessage("main.usage.summary", progname));478}479return EXIT_CMDERR;480} catch (InternalError e) {481Object[] e_args;482if (e.getCause() == null)483e_args = e.args;484else {485e_args = new Object[e.args.length + 1];486e_args[0] = e.getCause();487System.arraycopy(e.args, 0, e_args, 1, e.args.length);488}489reportError("err.internal.error", e_args);490return EXIT_ABNORMAL;491} finally {492log.flush();493}494}495496public void handleOptions(String[] args) throws BadArgs {497handleOptions(Arrays.asList(args), true);498}499500private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {501if (log == null) {502log = getPrintWriterForStream(System.out);503if (diagnosticListener == null)504diagnosticListener = getDiagnosticListenerForStream(System.err);505} else {506if (diagnosticListener == null)507diagnosticListener = getDiagnosticListenerForWriter(log);508}509510511if (fileManager == null)512fileManager = getDefaultFileManager(diagnosticListener, log);513514Iterator<String> iter = args.iterator();515boolean noArgs = !iter.hasNext();516517while (iter.hasNext()) {518String arg = iter.next();519if (arg.startsWith("-"))520handleOption(arg, iter);521else if (allowClasses) {522if (classes == null)523classes = new ArrayList<>();524classes.add(arg);525while (iter.hasNext())526classes.add(iter.next());527} else528throw new BadArgs("err.unknown.option", arg).showUsage(true);529}530531if (options.accessOptions.size() > 1) {532StringBuilder sb = new StringBuilder();533for (String opt: options.accessOptions) {534if (sb.length() > 0)535sb.append(" ");536sb.append(opt);537}538throw new BadArgs("err.incompatible.options", sb);539}540541if ((classes == null || classes.size() == 0) &&542!(noArgs || options.help || options.version || options.fullVersion)) {543throw new BadArgs("err.no.classes.specified");544}545546if (noArgs || options.help)547showHelp();548549if (options.version || options.fullVersion)550showVersion(options.fullVersion);551}552553private void handleOption(String name, Iterator<String> rest) throws BadArgs {554for (Option o: recognizedOptions) {555if (o.matches(name)) {556if (o.hasArg) {557if (rest.hasNext())558o.process(this, name, rest.next());559else560throw new BadArgs("err.missing.arg", name).showUsage(true);561} else562o.process(this, name, null);563564if (o.ignoreRest()) {565while (rest.hasNext())566rest.next();567}568return;569}570}571572try {573if (fileManager.handleOption(name, rest))574return;575} catch (IllegalArgumentException e) {576throw new BadArgs("err.invalid.use.of.option", name).showUsage(true);577}578579throw new BadArgs("err.unknown.option", name).showUsage(true);580}581582public Boolean call() {583return run() == 0;584}585586public int run() {587if (classes == null || classes.isEmpty()) {588return EXIT_ERROR;589}590591context.put(PrintWriter.class, log);592ClassWriter classWriter = ClassWriter.instance(context);593SourceWriter sourceWriter = SourceWriter.instance(context);594sourceWriter.setFileManager(fileManager);595596if (options.moduleName != null) {597try {598moduleLocation = findModule(options.moduleName);599if (moduleLocation == null) {600reportError("err.cant.find.module", options.moduleName);601return EXIT_ERROR;602}603} catch (IOException e) {604reportError("err.cant.find.module.ex", options.moduleName, e);605return EXIT_ERROR;606}607}608609int result = EXIT_OK;610611for (String className: classes) {612try {613result = writeClass(classWriter, className);614} catch (ConstantPoolException e) {615reportError("err.bad.constant.pool", className, e.getLocalizedMessage());616result = EXIT_ERROR;617} catch (EOFException e) {618reportError("err.end.of.file", className);619result = EXIT_ERROR;620} catch (FileNotFoundException | NoSuchFileException e) {621reportError("err.file.not.found", e.getLocalizedMessage());622result = EXIT_ERROR;623} catch (IOException e) {624//e.printStackTrace();625Object msg = e.getLocalizedMessage();626if (msg == null) {627msg = e;628}629reportError("err.ioerror", className, msg);630result = EXIT_ERROR;631} catch (OutOfMemoryError e) {632reportError("err.nomem");633result = EXIT_ERROR;634} catch (FatalError e) {635Object msg = e.getLocalizedMessage();636if (msg == null) {637msg = e;638}639reportError("err.fatal.err", msg);640result = EXIT_ERROR;641} catch (Throwable t) {642StringWriter sw = new StringWriter();643PrintWriter pw = new PrintWriter(sw);644t.printStackTrace(pw);645pw.close();646reportError("err.crash", t.toString(), sw.toString());647result = EXIT_ABNORMAL;648}649}650651return result;652}653654protected int writeClass(ClassWriter classWriter, String className)655throws IOException, ConstantPoolException {656JavaFileObject fo = open(className);657if (fo == null) {658reportError("err.class.not.found", className);659return EXIT_ERROR;660}661662ClassFileInfo cfInfo = read(fo);663if (!className.endsWith(".class")) {664if (cfInfo.cf.this_class == 0) {665if (!className.equals("module-info")) {666reportWarning("warn.unexpected.class", fo.getName(), className);667}668} else {669String cfName = cfInfo.cf.getName();670if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) {671reportWarning("warn.unexpected.class", fo.getName(), className);672}673}674}675write(cfInfo);676677if (options.showInnerClasses) {678ClassFile cf = cfInfo.cf;679Attribute a = cf.getAttribute(Attribute.InnerClasses);680if (a instanceof InnerClasses_attribute) {681InnerClasses_attribute inners = (InnerClasses_attribute) a;682try {683int result = EXIT_OK;684for (int i = 0; i < inners.classes.length; i++) {685int outerIndex = inners.classes[i].outer_class_info_index;686ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex);687String outerClassName = outerClassInfo.getName();688if (outerClassName.equals(cf.getName())) {689int innerIndex = inners.classes[i].inner_class_info_index;690ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex);691String innerClassName = innerClassInfo.getName();692classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));693classWriter.println();694result = writeClass(classWriter, innerClassName);695if (result != EXIT_OK) return result;696}697}698return result;699} catch (ConstantPoolException e) {700reportError("err.bad.innerclasses.attribute", className);701return EXIT_ERROR;702}703} else if (a != null) {704reportError("err.bad.innerclasses.attribute", className);705return EXIT_ERROR;706}707}708709return EXIT_OK;710}711712protected JavaFileObject open(String className) throws IOException {713// for compatibility, first see if it is a class name714JavaFileObject fo = getClassFileObject(className);715if (fo != null)716return fo;717718// see if it is an inner class, by replacing dots to $, starting from the right719String cn = className;720int lastDot;721while ((lastDot = cn.lastIndexOf(".")) != -1) {722cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);723fo = getClassFileObject(cn);724if (fo != null)725return fo;726}727728if (!className.endsWith(".class"))729return null;730731if (fileManager instanceof StandardJavaFileManager) {732StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;733try {734fo = sfm.getJavaFileObjects(className).iterator().next();735if (fo != null && fo.getLastModified() != 0) {736return fo;737}738} catch (IllegalArgumentException ignore) {739}740}741742// see if it is a URL, and if so, wrap it in just enough of a JavaFileObject743// to suit javap's needs744if (className.matches("^[A-Za-z]+:.*")) {745try {746final URI uri = new URI(className);747final URL url = uri.toURL();748final URLConnection conn = url.openConnection();749conn.setUseCaches(false);750return new JavaFileObject() {751public Kind getKind() {752return JavaFileObject.Kind.CLASS;753}754755public boolean isNameCompatible(String simpleName, Kind kind) {756throw new UnsupportedOperationException();757}758759public NestingKind getNestingKind() {760throw new UnsupportedOperationException();761}762763public Modifier getAccessLevel() {764throw new UnsupportedOperationException();765}766767public URI toUri() {768return uri;769}770771public String getName() {772return uri.toString();773}774775public InputStream openInputStream() throws IOException {776return conn.getInputStream();777}778779public OutputStream openOutputStream() throws IOException {780throw new UnsupportedOperationException();781}782783public Reader openReader(boolean ignoreEncodingErrors) throws IOException {784throw new UnsupportedOperationException();785}786787public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {788throw new UnsupportedOperationException();789}790791public Writer openWriter() throws IOException {792throw new UnsupportedOperationException();793}794795public long getLastModified() {796return conn.getLastModified();797}798799public boolean delete() {800throw new UnsupportedOperationException();801}802803};804} catch (URISyntaxException | IOException ignore) {805}806}807808return null;809}810811public static class ClassFileInfo {812ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {813this.fo = fo;814this.cf = cf;815this.digest = digest;816this.size = size;817}818public final JavaFileObject fo;819public final ClassFile cf;820public final byte[] digest;821public final int size;822}823824public ClassFileInfo read(JavaFileObject fo) throws IOException, ConstantPoolException {825InputStream in = fo.openInputStream();826try {827SizeInputStream sizeIn = null;828MessageDigest md = null;829if (options.sysInfo || options.verbose) {830try {831md = MessageDigest.getInstance("SHA-256");832} catch (NoSuchAlgorithmException ignore) {833}834in = new DigestInputStream(in, md);835in = sizeIn = new SizeInputStream(in);836}837838ClassFile cf = ClassFile.read(in, attributeFactory);839byte[] digest = (md == null) ? null : md.digest();840int size = (sizeIn == null) ? -1 : sizeIn.size();841return new ClassFileInfo(fo, cf, digest, size);842} finally {843in.close();844}845}846847public void write(ClassFileInfo info) {848ClassWriter classWriter = ClassWriter.instance(context);849if (options.sysInfo || options.verbose) {850classWriter.setFile(info.fo.toUri());851classWriter.setLastModified(info.fo.getLastModified());852classWriter.setDigest("SHA-256", info.digest);853classWriter.setFileSize(info.size);854}855856classWriter.write(info.cf);857}858859protected void setClassFile(ClassFile classFile) {860ClassWriter classWriter = ClassWriter.instance(context);861classWriter.setClassFile(classFile);862}863864protected void setMethod(Method enclosingMethod) {865ClassWriter classWriter = ClassWriter.instance(context);866classWriter.setMethod(enclosingMethod);867}868869protected void write(Attribute value) {870AttributeWriter attrWriter = AttributeWriter.instance(context);871ClassWriter classWriter = ClassWriter.instance(context);872ClassFile cf = classWriter.getClassFile();873attrWriter.write(cf, value, cf.constant_pool);874}875876protected void write(Attributes attrs) {877AttributeWriter attrWriter = AttributeWriter.instance(context);878ClassWriter classWriter = ClassWriter.instance(context);879ClassFile cf = classWriter.getClassFile();880attrWriter.write(cf, attrs, cf.constant_pool);881}882883protected void write(ConstantPool constant_pool) {884ConstantWriter constantWriter = ConstantWriter.instance(context);885constantWriter.writeConstantPool(constant_pool);886}887888protected void write(ConstantPool constant_pool, int value) {889ConstantWriter constantWriter = ConstantWriter.instance(context);890constantWriter.write(value);891}892893protected void write(ConstantPool.CPInfo value) {894ConstantWriter constantWriter = ConstantWriter.instance(context);895constantWriter.println(value);896}897898protected void write(Field value) {899ClassWriter classWriter = ClassWriter.instance(context);900classWriter.writeField(value);901}902903protected void write(Method value) {904ClassWriter classWriter = ClassWriter.instance(context);905classWriter.writeMethod(value);906}907908private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {909if (defaultFileManager == null)910defaultFileManager = JavapFileManager.create(dl, log);911return defaultFileManager;912}913914private JavaFileObject getClassFileObject(String className) throws IOException {915try {916JavaFileObject fo;917if (moduleLocation != null) {918fo = fileManager.getJavaFileForInput(moduleLocation, className, JavaFileObject.Kind.CLASS);919} else {920fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);921if (fo == null)922fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);923}924return fo;925} catch (IllegalArgumentException e) {926return null;927}928}929930private Location findModule(String moduleName) throws IOException {931Location[] locns = {932StandardLocation.UPGRADE_MODULE_PATH,933StandardLocation.SYSTEM_MODULES,934StandardLocation.MODULE_PATH935};936for (Location segment: locns) {937for (Set<Location> set: fileManager.listLocationsForModules(segment)) {938Location result = null;939for (Location l: set) {940String name = fileManager.inferModuleName(l);941if (name.equals(moduleName)) {942if (result == null)943result = l;944else945throw new IOException("multiple definitions found for " + moduleName);946}947}948if (result != null)949return result;950}951}952return null;953}954955private void showHelp() {956printLines(getMessage("main.usage", progname));957for (Option o: recognizedOptions) {958String name = o.aliases[0].replaceAll("^-+", "").replaceAll("-+", "_"); // there must always be at least one name959if (name.startsWith("X") || name.equals("fullversion"))960continue;961printLines(getMessage("main.opt." + name));962}963964String[] fmOptions = {965"--module-path", "--system",966"--class-path", "-classpath", "-cp",967"-bootclasspath",968"--multi-release"969};970971for (String o: fmOptions) {972if (fileManager.isSupportedOption(o) == -1)973continue;974String name = o.replaceAll("^-+", "").replaceAll("-+", "_");975printLines(getMessage("main.opt." + name));976}977978printLines(getMessage("main.usage.foot"));979}980981private void showVersion(boolean full) {982printLines(version(full ? "full" : "release"));983}984985private void printLines(String msg) {986log.println(msg.replace("\n", nl));987}988989private static final String nl = System.getProperty("line.separator");990991private static final String versionRBName = "com.sun.tools.javap.resources.version";992private static ResourceBundle versionRB;993994private String version(String key) {995// key=version: mm.nn.oo[-milestone]996// key=full: mm.mm.oo[-milestone]-build997if (versionRB == null) {998try {999versionRB = ResourceBundle.getBundle(versionRBName);1000} catch (MissingResourceException e) {1001return getMessage("version.resource.missing", System.getProperty("java.version"));1002}1003}1004try {1005return versionRB.getString(key);1006}1007catch (MissingResourceException e) {1008return getMessage("version.unknown", System.getProperty("java.version"));1009}1010}10111012private void reportError(String key, Object... args) {1013diagnosticListener.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));1014}10151016private void reportNote(String key, Object... args) {1017diagnosticListener.report(createDiagnostic(Diagnostic.Kind.NOTE, key, args));1018}10191020private void reportWarning(String key, Object... args) {1021diagnosticListener.report(createDiagnostic(Diagnostic.Kind.WARNING, key, args));1022}10231024private Diagnostic<JavaFileObject> createDiagnostic(1025final Diagnostic.Kind kind, final String key, final Object... args) {1026return new Diagnostic<>() {1027public Kind getKind() {1028return kind;1029}10301031public JavaFileObject getSource() {1032return null;1033}10341035public long getPosition() {1036return Diagnostic.NOPOS;1037}10381039public long getStartPosition() {1040return Diagnostic.NOPOS;1041}10421043public long getEndPosition() {1044return Diagnostic.NOPOS;1045}10461047public long getLineNumber() {1048return Diagnostic.NOPOS;1049}10501051public long getColumnNumber() {1052return Diagnostic.NOPOS;1053}10541055public String getCode() {1056return key;1057}10581059public String getMessage(Locale locale) {1060return JavapTask.this.getMessage(locale, key, args);1061}10621063@Override1064public String toString() {1065return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";1066}10671068};10691070}10711072public String getMessage(String key, Object... args) {1073return getMessage(task_locale, key, args);1074}10751076public String getMessage(Locale locale, String key, Object... args) {1077if (bundles == null) {1078// could make this a HashMap<Locale,SoftReference<ResourceBundle>>1079// and for efficiency, keep a hard reference to the bundle for the task1080// locale1081bundles = new HashMap<>();1082}10831084if (locale == null)1085locale = Locale.getDefault();10861087ResourceBundle b = bundles.get(locale);1088if (b == null) {1089try {1090b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale);1091bundles.put(locale, b);1092} catch (MissingResourceException e) {1093throw new InternalError("Cannot find javap resource bundle for locale " + locale);1094}1095}10961097try {1098return MessageFormat.format(b.getString(key), args);1099} catch (MissingResourceException e) {1100throw new InternalError(e, key);1101}1102}11031104protected Context context;1105JavaFileManager fileManager;1106JavaFileManager defaultFileManager;1107PrintWriter log;1108DiagnosticListener<? super JavaFileObject> diagnosticListener;1109List<String> classes;1110Location moduleLocation;1111Options options;1112//ResourceBundle bundle;1113Locale task_locale;1114Map<Locale, ResourceBundle> bundles;1115protected Attribute.Factory attributeFactory;11161117private static final String progname = "javap";11181119private static class SizeInputStream extends FilterInputStream {1120SizeInputStream(InputStream in) {1121super(in);1122}11231124int size() {1125return size;1126}11271128@Override1129public int read(byte[] buf, int offset, int length) throws IOException {1130int n = super.read(buf, offset, length);1131if (n > 0)1132size += n;1133return n;1134}11351136@Override1137public int read() throws IOException {1138int b = super.read();1139size += 1;1140return b;1141}11421143private int size;1144}1145}114611471148