src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File hotspot Sdiff src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc

src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java

Print this page




  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package jdk.tools.jaotc;
  25 
  26 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
  27 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
  28 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
  29 
  30 import java.io.BufferedReader;
  31 import java.io.File;
  32 import java.io.FileNotFoundException;
  33 import java.io.FileReader;
  34 import java.io.FileWriter;
  35 import java.io.IOException;
  36 import java.io.InputStream;
  37 import java.io.InputStreamReader;
  38 import java.io.PrintWriter;
  39 import java.lang.management.ManagementFactory;
  40 import java.lang.management.MemoryUsage;
  41 import java.nio.file.Path;
  42 import java.nio.file.Paths;
  43 import java.text.MessageFormat;
  44 import java.util.ArrayList;
  45 import java.util.Date;
  46 import java.util.HashSet;
  47 import java.util.LinkedList;
  48 import java.util.List;
  49 import java.util.ListIterator;
  50 import java.util.Set;
  51 import java.util.stream.Stream;
  52 
  53 import jdk.tools.jaotc.binformat.BinaryContainer;
  54 import jdk.tools.jaotc.binformat.ByteContainer;
  55 import jdk.tools.jaotc.collect.*;
  56 import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
  57 import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
  58 import jdk.tools.jaotc.collect.jar.JarSourceProvider;
  59 import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
  60 import jdk.tools.jaotc.utils.Timer;
  61 
  62 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  63 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
  64 import org.graalvm.compiler.debug.DebugContext;
  65 import org.graalvm.compiler.debug.DebugContext.Activation;
  66 import org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
  67 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  68 import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory;
  69 import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues;
  70 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
  71 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
  72 import org.graalvm.compiler.java.GraphBuilderPhase;
  73 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  74 import org.graalvm.compiler.options.OptionValues;
  75 import org.graalvm.compiler.phases.BasePhase;
  76 import org.graalvm.compiler.phases.PhaseSuite;
  77 import org.graalvm.compiler.phases.tiers.HighTierContext;
  78 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
  79 import org.graalvm.compiler.runtime.RuntimeProvider;
  80 
  81 import jdk.vm.ci.meta.MetaAccessProvider;
  82 import jdk.vm.ci.meta.ResolvedJavaMethod;
  83 import jdk.vm.ci.meta.ResolvedJavaType;
  84 import jdk.vm.ci.runtime.JVMCI;
  85 
  86 public class Main implements LogPrinter {
  87     static class BadArgs extends Exception {
  88         private static final long serialVersionUID = 1L;
  89         final String key;
  90         final Object[] args;
  91         boolean showUsage;
  92 
  93         BadArgs(String key, Object... args) {
  94             super(MessageFormat.format(key, args));
  95             this.key = key;
  96             this.args = args;
  97         }
  98 
  99         BadArgs showUsage(boolean b) {
 100             showUsage = b;
 101             return this;
 102         }
 103     }
 104 
 105     abstract static class Option {
 106         final String help;
 107         final boolean hasArg;
 108         final String[] aliases;
 109 
 110         Option(String help, boolean hasArg, String... aliases) {
 111             this.help = help;
 112             this.hasArg = hasArg;
 113             this.aliases = aliases;
 114         }
 115 
 116         boolean isHidden() {
 117             return false;
 118         }
 119 
 120         boolean matches(String opt) {
 121             for (String a : aliases) {
 122                 if (a.equals(opt)) {
 123                     return true;
 124                 } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
 125                     return true;
 126                 }
 127             }
 128             return false;
 129         }
 130 
 131         boolean ignoreRest() {
 132             return false;
 133         }
 134 
 135         abstract void process(Main task, String opt, String arg) throws BadArgs;
 136     }
 137 
 138     static Option[] recognizedOptions = {new Option("  --output <file>            Output file name", true, "--output") {
 139         @Override
 140         void process(Main task, String opt, String arg) {
 141             String name = arg;
 142             task.options.outputName = name;
 143         }
 144     }, new Option("  --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
 145         @Override
 146         void process(Main task, String opt, String arg) {
 147             task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
 148         }
 149     }, new Option("  --jar <jarfiles>           List of jar files to compile", true, "--jar") {
 150         @Override
 151         void process(Main task, String opt, String arg) {
 152             task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
 153         }
 154     }, new Option("  --module <modules>         List of modules to compile", true, "--module") {
 155         @Override
 156         void process(Main task, String opt, String arg) {
 157             task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
 158         }
 159     }, new Option("  --directory <dirs>         List of directories where to search for files to compile", true, "--directory") {
 160         @Override
 161         void process(Main task, String opt, String arg) {
 162             task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
 163         }
 164     }, new Option("  --search-path <dirs>       List of directories where to search for specified files", true, "--search-path") {
 165         @Override
 166         void process(Main task, String opt, String arg) {
 167             String[] elements = arg.split(":");
 168             task.options.searchPath.add(elements);
 169         }
 170     }, new Option("  --compile-commands <file>  Name of file with compile commands", true, "--compile-commands") {
 171         @Override
 172         void process(Main task, String opt, String arg) {
 173             task.options.methodList = arg;
 174         }
 175     }, new Option("  --compile-for-tiered       Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
 176         @Override
 177         void process(Main task, String opt, String arg) {
 178             task.options.tiered = true;
 179         }
 180     }, new Option("  --compile-with-assertions  Compile with java assertions", false, "--compile-with-assertions") {
 181         @Override
 182         void process(Main task, String opt, String arg) {
 183             task.options.compileWithAssertions = true;
 184         }
 185     }, new Option("  --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") {
 186         @Override
 187         void process(Main task, String opt, String arg) {
 188             int threads = Integer.parseInt(arg);
 189             final int available = Runtime.getRuntime().availableProcessors();
 190             if (threads <= 0) {
 191                 task.warning("invalid number of threads specified: {0}, using: {1}", threads, available);
 192                 threads = available;
 193             }
 194             if (threads > available) {
 195                 task.warning("too many threads specified: {0}, limiting to: {1}", threads, available);
 196             }
 197             task.options.threads = Integer.min(threads, available);
 198         }
 199     }, new Option("  --ignore-errors            Ignores all exceptions thrown during class loading", false, "--ignore-errors") {
 200         @Override
 201         void process(Main task, String opt, String arg) {
 202             task.options.ignoreClassLoadingErrors = true;
 203         }
 204     }, new Option("  --exit-on-error            Exit on compilation errors", false, "--exit-on-error") {
 205         @Override
 206         void process(Main task, String opt, String arg) {
 207             task.options.exitOnError = true;
 208         }
 209     }, new Option("  --info                     Print information during compilation", false, "--info") {
 210         @Override
 211         void process(Main task, String opt, String arg) throws BadArgs {
 212             task.options.info = true;
 213         }
 214     }, new Option("  --verbose                  Print verbose information", false, "--verbose") {
 215         @Override
 216         void process(Main task, String opt, String arg) throws BadArgs {
 217             task.options.info = true;
 218             task.options.verbose = true;
 219         }
 220     }, new Option("  --debug                    Print debug information", false, "--debug") {
 221         @Override
 222         void process(Main task, String opt, String arg) throws BadArgs {
 223             task.options.info = true;
 224             task.options.verbose = true;
 225             task.options.debug = true;
 226         }
 227     }, new Option("  --help                     Print this usage message", false, "--help") {
 228         @Override
 229         void process(Main task, String opt, String arg) {
 230             task.options.help = true;
 231         }
 232     }, new Option("  --version                  Version information", false, "--version") {
 233         @Override
 234         void process(Main task, String opt, String arg) {
 235             task.options.version = true;
 236         }
 237     }, new Option("  --linker-path              Full path to linker executable", true, "--linker-path") {
 238         @Override
 239         void process(Main task, String opt, String arg) {
 240             task.options.linkerpath = arg;
 241         }
 242     }, new Option("  -J<flag>                   Pass <flag> directly to the runtime system", false, "-J") {
 243         @Override
 244         void process(Main task, String opt, String arg) {
 245         }
 246     }};
 247 
 248     public static class Options {
 249         public List<SearchFor> files = new LinkedList<>();
 250         public String outputName = defaultOutputName();
 251         public String methodList;
 252         public List<ClassSource> sources = new ArrayList<>();
 253         public String linkerpath = null;
 254         public SearchPath searchPath = new SearchPath();
 255 
 256         /**
 257          * We don't see scaling beyond 16 threads.
 258          */
 259         private static final int COMPILER_THREADS = 16;
 260 
 261         public int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
 262 
 263         public boolean ignoreClassLoadingErrors;
 264         public boolean exitOnError;
 265         public boolean info;
 266         public boolean verbose;
 267         public boolean debug;
 268         public boolean help;
 269         public boolean version;
 270         public boolean compileWithAssertions;
 271         public boolean tiered;
 272 
 273         private static String defaultOutputName() {
 274             String osName = System.getProperty("os.name");
 275             String name = "unnamed.";
 276             String ext;
 277 
 278             switch (osName) {
 279                 case "Linux":
 280                 case "SunOS":
 281                     ext = "so";
 282                     break;
 283                 case "Mac OS X":
 284                     ext = "dylib";
 285                     break;
 286                 default:
 287                     if (osName.startsWith("Windows")) {
 288                         ext = "dll";
 289                     } else {
 290                         ext = "so";
 291                     }
 292             }
 293 
 294             return name + ext;
 295         }
 296     }
 297 
 298     /* package */final Options options = new Options();
 299 
 300     /**
 301      * Logfile.
 302      */
 303     private static FileWriter logFile = null;
 304 
 305     private static final int EXIT_OK = 0;        // No errors.
 306     private static final int EXIT_CMDERR = 2;    // Bad command-line arguments and/or switches.
 307     private static final int EXIT_ABNORMAL = 4;  // Terminated abnormally.
 308 
 309     private static final String PROGNAME = "jaotc";
 310 
 311     private static final String JVM_VERSION = System.getProperty("java.runtime.version");
 312 
 313     public static void main(String[] args) throws Exception {
 314         Main t = new Main();
 315         final int exitCode = t.run(args);
 316         System.exit(exitCode);
 317     }
 318 
 319     private int run(String[] args) {
 320         if (log == null) {
 321             log = new PrintWriter(System.out);
 322         }
 323 
 324         try {
 325             handleOptions(args);
 326             if (options.help) {
 327                 showHelp();
 328                 return EXIT_OK;
 329             }
 330             if (options.version) {
 331                 showVersion();
 332                 return EXIT_OK;
 333             }
 334 
 335             printlnInfo("Compiling " + options.outputName + "...");
 336             final long start = System.currentTimeMillis();
 337             if (!run()) {
 338                 return EXIT_ABNORMAL;
 339             }
 340             final long end = System.currentTimeMillis();
 341             printlnInfo("Total time: " + (end - start) + " ms");
 342 
 343             return EXIT_OK;
 344         } catch (BadArgs e) {
 345             reportError(e.key, e.args);
 346             if (e.showUsage) {
 347                 showUsage();
 348             }
 349             return EXIT_CMDERR;
 350         } catch (Exception e) {
 351             e.printStackTrace();
 352             return EXIT_ABNORMAL;
 353         } finally {
 354             log.flush();
 355         }
 356     }
 357 
 358     private static String humanReadableByteCount(long bytes) {
 359         int unit = 1024;
 360 
 361         if (bytes < unit) {
 362             return bytes + " B";
 363         }
 364 
 365         int exp = (int) (Math.log(bytes) / Math.log(unit));
 366         char pre = "KMGTPE".charAt(exp - 1);
 367         return String.format("%.1f %cB", bytes / Math.pow(unit, exp), pre);
 368     }
 369 
 370     void printMemoryUsage() {
 371         if (options.verbose) {
 372             MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
 373             float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
 374             log.format(" [used: %-7s, comm: %-7s, freeRatio ~= %.1f%%]",
 375                             humanReadableByteCount(memusage.getUsed()),
 376                             humanReadableByteCount(memusage.getCommitted()),
 377                             freeratio * 100);
 378         }
 379     }
 380 
 381     /**
 382      * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012
 383      */
 384     public enum VSVERSIONS {
 385         VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
 386         VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
 387         VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe");
 388 
 389         private final String envvariable;
 390         private final String wkp;
 391 
 392         VSVERSIONS(String envvariable, String wellknownpath) {
 393             this.envvariable = envvariable;
 394             this.wkp = wellknownpath;
 395         }
 396 
 397         String EnvVariable() {
 398             return envvariable;
 399         }
 400 
 401         String WellKnownPath() {
 402             return wkp;
 403         }
 404     }
 405 
 406     /**
 407      * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012
 408      */
 409     private static String getWindowsLinkPath() {
 410         String link = "\\VC\\bin\\amd64\\link.exe";
 411 
 412         /**
 413          * First try searching the paths pointed to by the VS environment variables.
 414          */
 415         for (VSVERSIONS vs : VSVERSIONS.values()) {
 416             String vspath = System.getenv(vs.EnvVariable());
 417             if (vspath != null) {
 418                 File commonTools = new File(vspath);
 419                 File vsRoot = commonTools.getParentFile().getParentFile();
 420                 File linkPath = new File(vsRoot, link);
 421                 if (linkPath.exists())
 422                     return linkPath.getPath();
 423             }
 424         }
 425 
 426         /**
 427          * If we didn't find via the VS environment variables, try the well known paths
 428          */
 429         for (VSVERSIONS vs : VSVERSIONS.values()) {
 430             String wkp = vs.WellKnownPath();
 431             if (new File(wkp).exists()) {
 432                 return wkp;
 433             }
 434         }
 435 
 436         return null;
 437     }
 438 
 439     @SuppressWarnings("try")
 440     private boolean run() throws Exception {
 441         openLog();
 442 
 443         try {
 444             CompilationSpec compilationRestrictions = collectSpecifiedMethods();
 445 
 446             Set<Class<?>> classesToCompile = new HashSet<>();



 447 
 448             try (Timer t = new Timer(this, "")) {
 449                 FileSupport fileSupport = new FileSupport();
 450                 ClassSearch lookup = new ClassSearch();
 451                 lookup.addProvider(new ModuleSourceProvider());
 452                 lookup.addProvider(new ClassNameSourceProvider(fileSupport));
 453                 lookup.addProvider(new JarSourceProvider());
 454                 lookup.addProvider(new DirectorySourceProvider(fileSupport));
 455 
 456                 List<LoadedClass> found = null;
 457                 try {
 458                     found = lookup.search(options.files, options.searchPath);
 459                 } catch (InternalError e) {
 460                     reportError(e);
 461                     return false;
 462                 }
 463 
 464                 for (LoadedClass loadedClass : found) {
 465                     classesToCompile.add(loadedClass.getLoadedClass());
 466                 }
 467 
 468                 printInfo(classesToCompile.size() + " classes found");
 469             }
 470 
 471             OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
 472             // Setting -Dgraal.TieredAOT overrides --compile-for-tiered
 473             if (!TieredAOT.hasBeenSet(graalOptions)) {
 474                 graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
 475             }
 476             graalOptions = new OptionValues(graalOptions, GeneratePIC, true, ImmutableCode, true);
 477             GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
 478             HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
 479             HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
 480             MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
 481             GraalFilters filters = new GraalFilters(metaAccess);
 482 
 483             List<AOTCompiledClass> classes;
 484 
 485             try (Timer t = new Timer(this, "")) {
 486                 classes = collectMethodsToCompile(classesToCompile, compilationRestrictions, filters, metaAccess);
 487             }
 488 
 489             // Free memory!
 490             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 491                 printMemoryUsage();
 492                 compilationRestrictions = null;
 493                 classesToCompile = null;
 494                 System.gc();
 495             }
 496 
 497             AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, filters);
 498             SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection();
 499             AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads);
 500             classes = compiler.compileClasses(classes);
 501 
 502             GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
 503             PhaseSuite<HighTierContext> graphBuilderSuite = aotBackend.getGraphBuilderSuite();
 504             ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
 505             GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
 506 
 507             // Free memory!
 508             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 509                 printMemoryUsage();
 510                 aotBackend = null;
 511                 compiler = null;
 512                 System.gc();
 513             }
 514 
 515             BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
 516             DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
 517 
 518             try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) {
 519                 dataBuilder.prepareData(debug);
 520             }
 521 
 522             // Print information about section sizes
 523             printContainerInfo(binaryContainer.getHeaderContainer().getContainer());
 524             printContainerInfo(binaryContainer.getConfigContainer());
 525             printContainerInfo(binaryContainer.getKlassesOffsetsContainer());
 526             printContainerInfo(binaryContainer.getMethodsOffsetsContainer());
 527             printContainerInfo(binaryContainer.getKlassesDependenciesContainer());
 528             printContainerInfo(binaryContainer.getStubsOffsetsContainer());
 529             printContainerInfo(binaryContainer.getMethodMetadataContainer());
 530             printContainerInfo(binaryContainer.getCodeContainer());
 531             printContainerInfo(binaryContainer.getCodeSegmentsContainer());
 532             printContainerInfo(binaryContainer.getConstantDataContainer());
 533             printContainerInfo(binaryContainer.getMetaspaceGotContainer());
 534             printContainerInfo(binaryContainer.getMetadataGotContainer());
 535             printContainerInfo(binaryContainer.getMethodStateContainer());
 536             printContainerInfo(binaryContainer.getOopGotContainer());
 537             printContainerInfo(binaryContainer.getMetaspaceNamesContainer());
 538 
 539             // Free memory!
 540             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 541                 printMemoryUsage();
 542                 backend = null;
 543                 for (AOTCompiledClass aotCompClass : classes) {
 544                     aotCompClass.clear();
 545                 }
 546                 classes.clear();
 547                 classes = null;
 548                 dataBuilder = null;
 549                 binaryContainer.freeMemory();
 550                 System.gc();
 551             }
 552 
 553             String name = options.outputName;
 554             String objectFileName = name;
 555 
 556             String libraryFileName = name;
 557 
 558             String linkerCmd;
 559             String linkerPath;
 560             String osName = System.getProperty("os.name");
 561 
 562             switch (osName) {
 563                 case "Linux":
 564                     if (name.endsWith(".so")) {
 565                         objectFileName = name.substring(0, name.length() - ".so".length());
 566                     }
 567                     linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
 568                     linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
 569                     break;
 570                 case "SunOS":
 571                     if (name.endsWith(".so")) {
 572                         objectFileName = name.substring(0, name.length() - ".so".length());
 573                     }
 574                     objectFileName = objectFileName + ".o";
 575                     linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
 576                     linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName;
 577                     break;
 578                 case "Mac OS X":
 579                     if (name.endsWith(".dylib")) {
 580                         objectFileName = name.substring(0, name.length() - ".dylib".length());
 581                     }
 582                     objectFileName = objectFileName + ".o";
 583                     linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
 584                     linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName;
 585                     break;
 586                 default:
 587                     if (osName.startsWith("Windows")) {
 588                         if (name.endsWith(".dll")) {
 589                             objectFileName = name.substring(0, name.length() - ".dll".length());
 590                         }
 591                         objectFileName = objectFileName + ".obj";
 592                         linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath();
 593                         if (linkerPath == null) {
 594                             throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe");
 595                         }
 596                         linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName;
 597                         break;
 598                     } else {
 599                         throw new InternalError("Unsupported platform: " + osName);
 600                     }
 601             }
 602 
 603             try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
 604                 binaryContainer.createBinary(objectFileName, JVM_VERSION);
 605             }
 606 
 607             // Free memory!
 608             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 609                 printMemoryUsage();
 610                 binaryContainer = null;
 611                 System.gc();
 612             }
 613 
 614             try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) {
 615                 Process p = Runtime.getRuntime().exec(linkerCmd);
 616                 final int exitCode = p.waitFor();
 617                 if (exitCode != 0) {
 618                     InputStream stderr = p.getErrorStream();
 619                     BufferedReader br = new BufferedReader(new InputStreamReader(stderr));
 620                     Stream<String> lines = br.lines();
 621                     StringBuilder sb = new StringBuilder();
 622                     lines.iterator().forEachRemaining(e -> sb.append(e));
 623                     throw new InternalError(sb.toString());
 624                 }
 625                 File objFile = new File(objectFileName);
 626                 if (objFile.exists()) {
 627                     if (!objFile.delete()) {
 628                         throw new InternalError("Failed to delete " + objectFileName + " file");
 629                     }
 630                 }
 631                 // Make non-executable for all.
 632                 File libFile = new File(libraryFileName);
 633                 if (libFile.exists() && !osName.startsWith("Windows")) {
 634                     if (!libFile.setExecutable(false, false)) {
 635                         throw new InternalError("Failed to change attribute for " + libraryFileName + " file");
 636                     }
 637                 }
 638             }
 639 
 640             printVerbose("Final memory  ");
 641             printMemoryUsage();
 642             printlnVerbose("");
 643 
 644         } finally {
 645             closeLog();
 646         }
 647         return true;
 648     }
 649 
 650     private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
 651         for (ResolvedJavaMethod m : methods) {
 652             addMethod(aotClass, m, compilationRestrictions, filters);
 653         }
 654     }
 655 
 656     private void addMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method, CompilationSpec compilationRestrictions, GraalFilters filters) {
 657         // Don't compile native or abstract methods.
 658         if (!method.hasBytecodes()) {
 659             return;
 660         }
 661         if (!compilationRestrictions.shouldCompileMethod(method)) {
 662             return;
 663         }
 664         if (!filters.shouldCompileMethod(method)) {
 665             return;
 666         }
 667 
 668         aotClass.addMethod(method);
 669         printlnVerbose("  added " + method.getName() + method.getSignature().toMethodDescriptor());
 670     }
 671 
 672     private void printContainerInfo(ByteContainer container) {
 673         printlnVerbose(container.getContainerName() + ": " + container.getByteStreamSize() + " bytes");
 674     }
 675 
 676     PrintWriter log;
 677 
 678     private void handleOptions(String[] args) throws BadArgs {
 679         if (args.length == 0) {
 680             options.help = true;
 681             return;
 682         }
 683 
 684         // Make checkstyle happy.
 685         int i = 0;
 686         for (; i < args.length; i++) {
 687             String arg = args[i];
 688 
 689             if (arg.charAt(0) == '-') {
 690                 Option option = getOption(arg);
 691                 String param = null;
 692 
 693                 if (option.hasArg) {
 694                     if (arg.startsWith("--") && arg.indexOf('=') > 0) {
 695                         param = arg.substring(arg.indexOf('=') + 1, arg.length());
 696                     } else if (i + 1 < args.length) {
 697                         param = args[++i];
 698                     }
 699 
 700                     if (param == null || param.isEmpty() || param.charAt(0) == '-') {
 701                         throw new BadArgs("missing argument for option: {0}", arg).showUsage(true);
 702                     }
 703                 }
 704 
 705                 option.process(this, arg, param);
 706 
 707                 if (option.ignoreRest()) {
 708                     break;
 709                 }
 710             } else {
 711                 options.files.add(new SearchFor(arg));
 712             }
 713         }
 714     }
 715 
 716     private static Option getOption(String name) throws BadArgs {
 717         for (Option o : recognizedOptions) {
 718             if (o.matches(name)) {
 719                 return o;
 720             }
 721         }
 722         throw new BadArgs("unknown option: {0}", name).showUsage(true);
 723     }
 724 
 725     public void printInfo(String message) {
 726         if (options.info) {
 727             log.print(message);
 728             log.flush();
 729         }
 730     }
 731 
 732     public void printlnInfo(String message) {
 733         if (options.info) {
 734             log.println(message);
 735             log.flush();
 736         }
 737     }
 738 
 739     public void printVerbose(String message) {
 740         if (options.verbose) {
 741             log.print(message);
 742             log.flush();
 743         }
 744     }
 745 
 746     public void printlnVerbose(String message) {
 747         if (options.verbose) {
 748             log.println(message);
 749             log.flush();
 750         }
 751     }
 752 
 753     public void printDebug(String message) {
 754         if (options.debug) {
 755             log.print(message);
 756             log.flush();
 757         }
 758     }
 759 
 760     public void printlnDebug(String message) {
 761         if (options.debug) {
 762             log.println(message);
 763             log.flush();
 764         }
 765     }
 766 
 767     public void printError(String message) {
 768         log.println("Error: " + message);
 769         log.flush();
 770     }
 771 
 772     private void reportError(Throwable e) {
 773         log.println("Error: " + e.getMessage());
 774         if (options.info) {
 775             e.printStackTrace(log);
 776         }
 777         log.flush();
 778     }
 779 
 780     private void reportError(String key, Object... args) {
 781         printError(MessageFormat.format(key, args));

 782     }
 783 
 784     private void warning(String key, Object... args) {
 785         log.println("Warning: " + MessageFormat.format(key, args));
 786         log.flush();
 787     }
 788 
 789     private void showUsage() {
 790         log.println("Usage: " + PROGNAME + " <options> list");
 791         log.println("use --help for a list of possible options");

 792     }
 793 
 794     private void showHelp() {
 795         log.println("Usage: " + PROGNAME + " <options> list");
 796         log.println();
 797         log.println("  list       A : separated list of class names, modules, jar files");
 798         log.println("             or directories which contain class files.");
 799         log.println();
 800         log.println("where options include:");
 801         for (Option o : recognizedOptions) {
 802             String name = o.aliases[0].substring(1); // there must always be at least one name
 803             name = name.charAt(0) == '-' ? name.substring(1) : name;
 804             if (o.isHidden() || name.equals("h")) {
 805                 continue;
 806             }
 807             log.println(o.help);
 808         }

 809     }
 810 
 811     private void showVersion() {
 812         log.println(PROGNAME + " " + JVM_VERSION);
 813     }
 814 
 815     /**
 816      * Collect all method we should compile.
 817      *
 818      * @return array list of AOT classes which have compiled methods.
 819      */
 820     private List<AOTCompiledClass> collectMethodsToCompile(Set<Class<?>> classesToCompile, CompilationSpec compilationRestrictions, GraalFilters filters, MetaAccessProvider metaAccess) {
 821         int total = 0;
 822         int count = 0;
 823         List<AOTCompiledClass> classes = new ArrayList<>();
 824 
 825         for (Class<?> c : classesToCompile) {
 826             ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c);
 827             if (filters.shouldCompileAnyMethodInClass(resolvedJavaType)) {
 828                 AOTCompiledClass aotClass = new AOTCompiledClass(resolvedJavaType);
 829                 printlnVerbose(" Scanning " + c.getName());
 830 
 831                 // Constructors
 832                 try {
 833                     ResolvedJavaMethod[] ctors = resolvedJavaType.getDeclaredConstructors();
 834                     addMethods(aotClass, ctors, compilationRestrictions, filters);
 835                     total += ctors.length;
 836                 } catch (Throwable e) {
 837                     // If we are running in JCK mode we ignore all exceptions.
 838                     if (options.ignoreClassLoadingErrors) {
 839                         printError(c.getName() + ": " + e);
 840                     } else {
 841                         throw new InternalError(e);
 842                     }
 843                 }
 844 
 845                 // Methods
 846                 try {
 847                     ResolvedJavaMethod[] methods = resolvedJavaType.getDeclaredMethods();
 848                     addMethods(aotClass, methods, compilationRestrictions, filters);
 849                     total += methods.length;
 850                 } catch (Throwable e) {
 851                     // If we are running in JCK mode we ignore all exceptions.
 852                     if (options.ignoreClassLoadingErrors) {
 853                         printError(c.getName() + ": " + e);
 854                     } else {
 855                         throw new InternalError(e);
 856                     }
 857                 }
 858 
 859                 // Class initializer
 860                 try {
 861                     ResolvedJavaMethod clinit = resolvedJavaType.getClassInitializer();
 862                     if (clinit != null) {
 863                         addMethod(aotClass, clinit, compilationRestrictions, filters);
 864                         total++;
 865                     }
 866                 } catch (Throwable e) {
 867                     // If we are running in JCK mode we ignore all exceptions.
 868                     if (options.ignoreClassLoadingErrors) {
 869                         printError(c.getName() + ": " + e);
 870                     } else {
 871                         throw new InternalError(e);
 872                     }
 873                 }
 874 
 875                 // Found any methods to compile? Add the class.
 876                 if (aotClass.hasMethods()) {
 877                     classes.add(aotClass);
 878                     count += aotClass.getMethodCount();
 879                 }
 880             }
 881         }
 882         printInfo(total + " methods total, " + count + " methods to compile");
 883         return classes;
 884     }
 885 
 886     /**
 887      * If a file with compilation limitations is specified using the java property
 888      * jdk.tools.jaotc.compile.method.list, read the file's contents and collect the restrictions.
 889      */
 890     private CompilationSpec collectSpecifiedMethods() {
 891         CompilationSpec compilationRestrictions = new CompilationSpec();
 892         String methodListFileName = options.methodList;
 893 
 894         if (methodListFileName != null && !methodListFileName.equals("")) {
 895             try {
 896                 FileReader methListFile = new FileReader(methodListFileName);
 897                 BufferedReader readBuf = new BufferedReader(methListFile);
 898                 String line = null;
 899                 while ((line = readBuf.readLine()) != null) {
 900                     String trimmedLine = line.trim();
 901                     if (!trimmedLine.startsWith("#")) {
 902                         String[] components = trimmedLine.split(" ");
 903                         if (components.length == 2) {
 904                             String directive = components[0];
 905                             String pattern = components[1];
 906                             switch (directive) {
 907                                 case "compileOnly":
 908                                     compilationRestrictions.addCompileOnlyPattern(pattern);
 909                                     break;
 910                                 case "exclude":
 911                                     compilationRestrictions.addExcludePattern(pattern);
 912                                     break;
 913                                 default:
 914                                     System.out.println("Unrecognized command " + directive + ". Ignoring\n\t" + line + "\n encountered in " + methodListFileName);
 915                             }
 916                         } else {
 917                             if (!trimmedLine.equals("")) {
 918                                 System.out.println("Ignoring malformed line:\n\t " + line + "\n");
 919                             }
 920                         }
 921                     }
 922                 }
 923                 readBuf.close();
 924             } catch (FileNotFoundException e) {
 925                 throw new InternalError("Unable to open method list file: " + methodListFileName, e);
 926             } catch (IOException e) {
 927                 throw new InternalError("Unable to read method list file: " + methodListFileName, e);
 928             }
 929         }
 930 
 931         return compilationRestrictions;
 932     }
 933 
 934     private static void openLog() {
 935         int v = Integer.getInteger("jdk.tools.jaotc.logCompilation", 0);
 936         if (v == 0) {
 937             logFile = null;
 938             return;
 939         }
 940         // Create log file in current directory
 941         String fileName = "aot_compilation" + new Date().getTime() + ".log";
 942         Path logFilePath = Paths.get("./", fileName);
 943         String logFileName = logFilePath.toString();
 944         try {
 945             // Create file to which we do not append
 946             logFile = new FileWriter(logFileName, false);
 947         } catch (IOException e) {
 948             System.out.println("Unable to open logfile :" + logFileName + "\nNo logs will be created");
 949             logFile = null;
 950         }
 951     }
 952 
 953     public static void writeLog(String str) {
 954         if (logFile != null) {
 955             try {
 956                 logFile.write(str + "\n");
 957                 logFile.flush();
 958             } catch (IOException e) {
 959                 // Print to console
 960                 System.out.println(str + "\n");
 961             }
 962         }
 963     }
 964 
 965     public static void closeLog() {
 966         if (logFile != null) {
 967             try {
 968                 logFile.close();
 969             } catch (IOException e) {
 970                 // Do nothing
 971             }
 972         }
 973     }
 974 }


  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package jdk.tools.jaotc;
  25 
  26 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
  27 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
  28 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
  29 








  30 import java.io.PrintWriter;




  31 import java.text.MessageFormat;




  32 import java.util.List;
  33 import java.util.ListIterator;
  34 import java.util.Set;

  35 
  36 import jdk.tools.jaotc.binformat.BinaryContainer;
  37 import jdk.tools.jaotc.Options.Option;






  38 
  39 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  40 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
  41 import org.graalvm.compiler.debug.DebugContext;
  42 import org.graalvm.compiler.debug.DebugContext.Activation;
  43 import org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
  44 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  45 import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory;
  46 import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues;
  47 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
  48 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
  49 import org.graalvm.compiler.java.GraphBuilderPhase;
  50 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  51 import org.graalvm.compiler.options.OptionValues;
  52 import org.graalvm.compiler.phases.BasePhase;
  53 import org.graalvm.compiler.phases.PhaseSuite;
  54 import org.graalvm.compiler.phases.tiers.HighTierContext;
  55 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
  56 import org.graalvm.compiler.runtime.RuntimeProvider;
  57 
  58 import jdk.vm.ci.meta.MetaAccessProvider;
  59 import jdk.vm.ci.meta.ResolvedJavaMethod;

  60 import jdk.vm.ci.runtime.JVMCI;
  61 
  62 public final class Main {





  63 
  64     final Options options = new Options();
  65     private PrintWriter log;
  66     LogPrinter printer;
  67     GraalFilters filters;















































































































































































































  68 
  69     private static final int EXIT_OK = 0;        // No errors.
  70     private static final int EXIT_CMDERR = 2;    // Bad command-line arguments and/or switches.
  71     private static final int EXIT_ABNORMAL = 4;  // Terminated abnormally.
  72 
  73     private static final String PROGNAME = "jaotc";
  74 
  75     private static final String JVM_VERSION = System.getProperty("java.runtime.version");
  76 
  77     public static void main(String[] args) throws Exception {
  78         Main t = new Main();
  79         final int exitCode = t.run(args);
  80         System.exit(exitCode);
  81     }
  82 
  83     private int run(String[] args) {

  84         log = new PrintWriter(System.out);
  85         printer = new LogPrinter(this, log);
  86 
  87         try {
  88             Options.handleOptions(this, args);
  89             if (options.help) {
  90                 showHelp();
  91                 return EXIT_OK;
  92             }
  93             if (options.version) {
  94                 showVersion();
  95                 return EXIT_OK;
  96             }
  97 
  98             printer.printlnInfo("Compiling " + options.outputName + "...");
  99             final long start = System.currentTimeMillis();
 100             if (!run()) {
 101                 return EXIT_ABNORMAL;
 102             }
 103             final long end = System.currentTimeMillis();
 104             printer.printlnInfo("Total time: " + (end - start) + " ms");
 105 
 106             return EXIT_OK;
 107         } catch (Options.BadArgs e) {
 108             printer.reportError(e.key, e.args);
 109             if (e.showUsage) {
 110                 showUsage();
 111             }
 112             return EXIT_CMDERR;
 113         } catch (Exception e) {
 114             e.printStackTrace();
 115             return EXIT_ABNORMAL;
 116         } finally {
 117             log.flush();
 118         }
 119     }
 120 

















































































 121     @SuppressWarnings("try")
 122     private boolean run() throws Exception {
 123         LogPrinter.openLog();
 124 
 125         try {

 126 
 127             final Linker linker = new Linker(this);
 128             final String objectFileName = linker.objFile();
 129             final Collector collector = new Collector(this);
 130             Set<Class<?>> classesToCompile;
 131 
 132             try (Timer t = new Timer(this, "")) {
 133                 classesToCompile = collector.collectClassesToCompile();
 134                 printer.printInfo(classesToCompile.size() + " classes found");


















 135             }
 136 
 137             OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
 138             // Setting -Dgraal.TieredAOT overrides --compile-for-tiered
 139             if (!TieredAOT.hasBeenSet(graalOptions)) {
 140                 graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
 141             }
 142             graalOptions = new OptionValues(graalOptions, GeneratePIC, true, ImmutableCode, true);
 143             GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
 144             HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
 145             HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
 146             MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
 147             filters = new GraalFilters(metaAccess);
 148 
 149             List<AOTCompiledClass> classes;
 150 
 151             try (Timer t = new Timer(this, "")) {
 152                 classes = collector.collectMethodsToCompile(classesToCompile, metaAccess);
 153             }
 154 
 155             // Free memory!
 156             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 157                 printer.printMemoryUsage();

 158                 classesToCompile = null;
 159                 System.gc();
 160             }
 161 
 162             AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend);
 163             SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection();
 164             AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads);
 165             classes = compiler.compileClasses(classes);
 166 
 167             GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
 168             PhaseSuite<HighTierContext> graphBuilderSuite = aotBackend.getGraphBuilderSuite();
 169             ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
 170             GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
 171 
 172             // Free memory!
 173             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 174                 printer.printMemoryUsage();
 175                 aotBackend = null;
 176                 compiler = null;
 177                 System.gc();
 178             }
 179 
 180             BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
 181             DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
 182 
 183             try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) {
 184                 dataBuilder.prepareData(debug);
 185             }
 186 
 187             // Print information about section sizes
 188             printer.containersInfo(binaryContainer);














 189 
 190             // Free memory!
 191             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 192                 printer.printMemoryUsage();
 193                 backend = null;
 194                 for (AOTCompiledClass aotCompClass : classes) {
 195                     aotCompClass.clear();
 196                 }
 197                 classes.clear();
 198                 classes = null;
 199                 dataBuilder = null;
 200                 binaryContainer.freeMemory();
 201                 System.gc();
 202             }
 203 


















































 204             try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
 205                 binaryContainer.createBinary(objectFileName);
 206             }
 207 
 208             // Free memory!
 209             try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
 210                 printer.printMemoryUsage();
 211                 binaryContainer = null;
 212                 System.gc();
 213             }
 214 
 215             try (Timer t = new Timer(this, "Creating shared library: " + linker.libFile())) {
 216                 linker.link();






















 217             }
 218 
 219             printer.printVerbose("Final memory  ");
 220             printer.printMemoryUsage();
 221             printer.printlnVerbose("");
 222 
 223         } finally {
 224             LogPrinter.closeLog();
 225         }
 226         return true;
 227     }
 228 
 229     void handleError(ResolvedJavaMethod resolvedMethod, Throwable e, String message) {
 230         String methodName = JavaMethodInfo.uniqueMethodName(resolvedMethod);



















 231 
 232         if (options.debug) {
 233             printer.printError("Failed compilation: " + methodName + ": " + e);
 234         }
 235 
 236         // Ignore some exceptions when meta-compiling Graal.
 237         if (GraalFilters.shouldIgnoreException(e)) {



 238             return;
 239         }
 240 
 241         LogPrinter.writeLog("Failed compilation of method " + methodName + message);



 242 
 243         if (!options.debug) {
 244             printer.printError("Failed compilation: " + methodName + ": " + e);























 245         }
 246 































 247         if (options.verbose) {



























 248             e.printStackTrace(log);
 249         }


 250 
 251         if (options.exitOnError) {
 252             System.exit(1);
 253         }
 254     }
 255 
 256     void warning(String key, Object... args) {
 257         log.println("Warning: " + MessageFormat.format(key, args));
 258         log.flush();
 259     }
 260 
 261     private void showUsage() {
 262         log.println("Usage: " + PROGNAME + " <options> list");
 263         log.println("use --help for a list of possible options");
 264         log.flush();
 265     }
 266 
 267     private void showHelp() {
 268         log.println("Usage: " + PROGNAME + " <options> list");
 269         log.println();
 270         log.println("  list       A : separated list of class names, modules, jar files");
 271         log.println("             or directories which contain class files.");
 272         log.println();
 273         log.println("where options include:");
 274         for (Option o : Options.recognizedOptions) {
 275             String name = o.aliases[0].substring(1); // there must always be at least one name
 276             name = name.charAt(0) == '-' ? name.substring(1) : name;
 277             if (o.isHidden() || name.equals("h")) {
 278                 continue;
 279             }
 280             log.println(o.help);
 281         }
 282         log.flush();
 283     }
 284 
 285     private void showVersion() {
 286         log.println(PROGNAME + " " + JVM_VERSION);
 287     }
































































































































































 288 }
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File