1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 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.LinkedList; 47 import java.util.List; 48 import java.util.Set; 49 import java.util.stream.Stream; 50 51 import jdk.tools.jaotc.binformat.BinaryContainer; 52 import jdk.tools.jaotc.binformat.ByteContainer; 53 import jdk.tools.jaotc.collect.ClassCollector; 54 import jdk.tools.jaotc.utils.Timer; 55 56 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; 57 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 58 import org.graalvm.compiler.hotspot.HotSpotHostBackend; 59 import org.graalvm.compiler.runtime.RuntimeProvider; 60 61 import jdk.vm.ci.meta.MetaAccessProvider; 62 import jdk.vm.ci.meta.ResolvedJavaMethod; 63 import jdk.vm.ci.meta.ResolvedJavaType; 64 import jdk.vm.ci.runtime.JVMCI; 65 66 public class Main implements LogPrinter { 67 static { 68 GeneratePIC.setValue(true); 69 ImmutableCode.setValue(true); 70 } 71 72 static class BadArgs extends Exception { 73 private static final long serialVersionUID = 1L; 74 final String key; 75 final Object[] args; 76 boolean showUsage; 77 78 BadArgs(String key, Object... args) { 79 super(MessageFormat.format(key, args)); 80 this.key = key; 81 this.args = args; 82 } 83 84 BadArgs showUsage(boolean b) { 85 showUsage = b; 86 return this; 87 } 88 } 89 90 abstract static class Option { 91 final String help; 92 final boolean hasArg; 93 final String[] aliases; 94 95 Option(String help, boolean hasArg, String... aliases) { 96 this.help = help; 97 this.hasArg = hasArg; 98 this.aliases = aliases; 99 } 100 101 boolean isHidden() { 102 return false; 103 } 104 105 boolean matches(String opt) { 106 for (String a : aliases) { 107 if (a.equals(opt)) { 108 return true; 109 } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) { 110 return true; 111 } 112 } 113 return false; 114 } 115 116 boolean ignoreRest() { 117 return false; 118 } 119 120 abstract void process(Main task, String opt, String arg) throws BadArgs; 121 } 122 123 static Option[] recognizedOptions = {new Option(" --module <name> Module to compile", true, "--module") { 124 @Override 125 void process(Main task, String opt, String arg) { 126 task.options.module = arg; 127 } 128 }, new Option(" --module-path <path> Specify where to find module to compile", true, "--module-path") { 129 @Override 130 void process(Main task, String opt, String arg) { 131 task.options.modulepath = arg; 132 } 133 }, new Option(" --output <file> Output file name", true, "--output") { 134 @Override 135 void process(Main task, String opt, String arg) { 136 String name = arg; 137 if (name.endsWith(".so")) { 138 name = name.substring(0, name.length() - ".so".length()); 139 } 140 task.options.outputName = name; 141 } 142 }, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") { 143 @Override 144 void process(Main task, String opt, String arg) { 145 task.options.methodList = arg; 146 } 147 }, new Option(" --compile-for-tiered Generated profiling code for tiered compilation", false, "--compile-for-tiered") { 148 @Override 149 void process(Main task, String opt, String arg) { 150 TieredAOT.setValue(true); 151 } 152 }, new Option(" --classpath <path> Specify where to find user class files", true, "--classpath", "--class-path") { 153 @Override 154 void process(Main task, String opt, String arg) { 155 task.options.classpath = arg; 156 } 157 }, new Option(" --threads <number> Number of compilation threads to be used", true, "--threads") { 158 @Override 159 void process(Main task, String opt, String arg) { 160 int threads = Integer.parseInt(arg); 161 final int available = Runtime.getRuntime().availableProcessors(); 162 if (threads <= 0) { 163 task.warning("invalid number of threads specified: {0}, using: {1}", threads, available); 164 threads = available; 165 } 166 if (threads > available) { 167 task.warning("too many threads specified: {0}, limiting to: {1}", threads, available); 168 } 169 task.options.threads = Integer.min(threads, available); 170 } 171 }, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") { 172 @Override 173 void process(Main task, String opt, String arg) { 174 task.options.ignoreClassLoadingErrors = true; 175 } 176 }, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") { 177 @Override 178 void process(Main task, String opt, String arg) { 179 task.options.exitOnError = true; 180 } 181 }, new Option(" --info Print information during compilation", false, "--info") { 182 @Override 183 void process(Main task, String opt, String arg) throws BadArgs { 184 task.options.info = true; 185 } 186 }, new Option(" --verbose Print verbose information", false, "--verbose") { 187 @Override 188 void process(Main task, String opt, String arg) throws BadArgs { 189 task.options.info = true; 190 task.options.verbose = true; 191 } 192 }, new Option(" --debug Print debug information", false, "--debug") { 193 @Override 194 void process(Main task, String opt, String arg) throws BadArgs { 195 task.options.info = true; 196 task.options.verbose = true; 197 task.options.debug = true; 198 } 199 }, new Option(" --help Print this usage message", false, "--help") { 200 @Override 201 void process(Main task, String opt, String arg) { 202 task.options.help = true; 203 } 204 }, new Option(" --version Version information", false, "--version") { 205 @Override 206 void process(Main task, String opt, String arg) { 207 task.options.version = true; 208 } 209 }, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") { 210 @Override 211 void process(Main task, String opt, String arg) { 212 } 213 }}; 214 215 public static class Options { 216 public List<String> files = new LinkedList<>(); 217 public String module = null; 218 public String modulepath = "modules"; 219 public String outputName = "unnamed"; 220 public String methodList; 221 public String classpath = "."; 222 223 /** 224 * We don't see scaling beyond 16 threads. 225 */ 226 private static final int COMPILER_THREADS = 16; 227 228 int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors()); 229 230 public boolean ignoreClassLoadingErrors; 231 public boolean exitOnError; 232 boolean info; 233 boolean verbose; 234 boolean debug; 235 boolean help; 236 boolean version; 237 } 238 239 /* package */final Options options = new Options(); 240 241 /** 242 * Logfile. 243 */ 244 private static FileWriter logFile = null; 245 246 private static final int EXIT_OK = 0; // No errors. 247 private static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches. 248 private static final int EXIT_ABNORMAL = 4; // Terminated abnormally. 249 250 private static final String PROGNAME = "jaotc"; 251 252 private static final String JVM_VERSION = System.getProperty("java.runtime.version"); 253 254 public static void main(String[] args) throws Exception { 255 Main t = new Main(); 256 final int exitCode = t.run(args); 257 System.exit(exitCode); 258 } 259 260 private int run(String[] args) { 261 if (log == null) { 262 log = new PrintWriter(System.out); 263 } 264 265 try { 266 handleOptions(args); 267 if (options.help) { 268 showHelp(); 269 return EXIT_OK; 270 } 271 if (options.version) { 272 showVersion(); 273 return EXIT_OK; 274 } 275 276 printlnInfo("Compiling " + options.outputName + "..."); 277 final long start = System.currentTimeMillis(); 278 run(); 279 final long end = System.currentTimeMillis(); 280 printlnInfo("Total time: " + (end - start) + " ms"); 281 282 return EXIT_OK; 283 } catch (BadArgs e) { 284 reportError(e.key, e.args); 285 if (e.showUsage) { 286 showUsage(); 287 } 288 return EXIT_CMDERR; 289 } catch (Exception e) { 290 e.printStackTrace(); 291 return EXIT_ABNORMAL; 292 } finally { 293 log.flush(); 294 } 295 } 296 297 private static String humanReadableByteCount(long bytes) { 298 int unit = 1024; 299 300 if (bytes < unit) { 301 return bytes + " B"; 302 } 303 304 int exp = (int) (Math.log(bytes) / Math.log(unit)); 305 char pre = "KMGTPE".charAt(exp - 1); 306 return String.format("%.1f %cB", bytes / Math.pow(unit, exp), pre); 307 } 308 309 void printMemoryUsage() { 310 if (options.verbose) { 311 MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); 312 float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted(); 313 log.format(" [used: %-7s, comm: %-7s, freeRatio ~= %.1f%%]", 314 humanReadableByteCount(memusage.getUsed()), 315 humanReadableByteCount(memusage.getCommitted()), 316 freeratio * 100); 317 } 318 } 319 320 @SuppressWarnings("try") 321 private void run() throws Exception { 322 openLog(); 323 324 try { 325 CompilationSpec compilationRestrictions = collectSpecifiedMethods(); 326 327 Set<Class<?>> classesToCompile; 328 329 try (Timer t = new Timer(this, "")) { 330 ClassCollector collector = new ClassCollector(this.options, this); 331 classesToCompile = collector.collectClassesToCompile(); 332 printInfo(classesToCompile.size() + " classes found"); 333 } 334 335 GraalJVMCICompiler graalCompiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler(); 336 HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime(); 337 HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend(); 338 MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess(); 339 GraalFilters filters = new GraalFilters(metaAccess); 340 341 List<AOTCompiledClass> classes; 342 343 try (Timer t = new Timer(this, "")) { 344 classes = collectMethodsToCompile(classesToCompile, compilationRestrictions, filters, metaAccess); 345 } 346 347 // Free memory! 348 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 349 printMemoryUsage(); 350 compilationRestrictions = null; 351 classesToCompile = null; 352 System.gc(); 353 } 354 355 AOTBackend aotBackend = new AOTBackend(this, backend, filters); 356 AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads); 357 classes = compiler.compileClasses(classes); 358 359 // Free memory! 360 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 361 printMemoryUsage(); 362 aotBackend = null; 363 compiler = null; 364 System.gc(); 365 } 366 367 BinaryContainer binaryContainer = new BinaryContainer(runtime.getVMConfig(), JVM_VERSION); 368 DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer); 369 dataBuilder.prepareData(); 370 371 // Print information about section sizes 372 printContainerInfo(binaryContainer.getHeaderContainer().getContainer()); 373 printContainerInfo(binaryContainer.getConfigContainer()); 374 printContainerInfo(binaryContainer.getKlassesOffsetsContainer()); 375 printContainerInfo(binaryContainer.getMethodsOffsetsContainer()); 376 printContainerInfo(binaryContainer.getKlassesDependenciesContainer()); 377 printContainerInfo(binaryContainer.getStubsOffsetsContainer()); 378 printContainerInfo(binaryContainer.getMethodMetadataContainer()); 379 printContainerInfo(binaryContainer.getCodeContainer()); 380 printContainerInfo(binaryContainer.getCodeSegmentsContainer()); 381 printContainerInfo(binaryContainer.getConstantDataContainer()); 382 printContainerInfo(binaryContainer.getMetaspaceGotContainer()); 383 printContainerInfo(binaryContainer.getMetadataGotContainer()); 384 printContainerInfo(binaryContainer.getMethodStateContainer()); 385 printContainerInfo(binaryContainer.getOopGotContainer()); 386 printContainerInfo(binaryContainer.getMetaspaceNamesContainer()); 387 388 // Free memory! 389 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 390 printMemoryUsage(); 391 backend = null; 392 for (AOTCompiledClass aotCompClass : classes) { 393 aotCompClass.clear(); 394 } 395 classes.clear(); 396 classes = null; 397 dataBuilder = null; 398 binaryContainer.freeMemory(); 399 System.gc(); 400 } 401 402 String objectFileName = options.outputName + ".o"; 403 String libraryFileName = options.outputName + ".so"; 404 405 try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) { 406 binaryContainer.createBinary(objectFileName, JVM_VERSION); 407 } 408 409 // Free memory! 410 try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) { 411 printMemoryUsage(); 412 binaryContainer = null; 413 System.gc(); 414 } 415 416 try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) { 417 Process p = Runtime.getRuntime().exec("ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName); 418 final int exitCode = p.waitFor(); 419 if (exitCode != 0) { 420 InputStream stderr = p.getErrorStream(); 421 BufferedReader br = new BufferedReader(new InputStreamReader(stderr)); 422 Stream<String> lines = br.lines(); 423 StringBuilder sb = new StringBuilder(); 424 lines.iterator().forEachRemaining(e -> sb.append(e)); 425 throw new InternalError(sb.toString()); 426 } 427 File objFile = new File(objectFileName); 428 if (objFile.exists()) { 429 if (!objFile.delete()) { 430 throw new InternalError("Failed to delete " + objectFileName + " file"); 431 } 432 } 433 // Make non-executable for all. 434 File libFile = new File(libraryFileName); 435 if (libFile.exists()) { 436 if (!libFile.setExecutable(false, false)) { 437 throw new InternalError("Failed to change attribute for " + libraryFileName + " file"); 438 } 439 } 440 } 441 442 printVerbose("Final memory "); 443 printMemoryUsage(); 444 printlnVerbose(""); 445 446 } finally { 447 closeLog(); 448 } 449 } 450 451 private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) { 452 for (ResolvedJavaMethod m : methods) { 453 addMethod(aotClass, m, compilationRestrictions, filters); 454 } 455 } 456 457 private void addMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method, CompilationSpec compilationRestrictions, GraalFilters filters) { 458 // Don't compile native or abstract methods. 459 if (!method.hasBytecodes()) { 460 return; 461 } 462 if (!compilationRestrictions.shouldCompileMethod(method)) { 463 return; 464 } 465 if (!filters.shouldCompileMethod(method)) { 466 return; 467 } 468 469 aotClass.addMethod(method); 470 printlnVerbose(" added " + method.getName() + method.getSignature().toMethodDescriptor()); 471 } 472 473 private void printContainerInfo(ByteContainer container) { 474 printlnVerbose(container.getContainerName() + ": " + container.getByteStreamSize() + " bytes"); 475 } 476 477 PrintWriter log; 478 479 private void handleOptions(String[] args) throws BadArgs { 480 if (args.length == 0) { 481 options.help = true; 482 return; 483 } 484 485 // Make checkstyle happy. 486 int i = 0; 487 for (; i < args.length; i++) { 488 String arg = args[i]; 489 490 if (arg.charAt(0) == '-') { 491 Option option = getOption(arg); 492 String param = null; 493 494 if (option.hasArg) { 495 if (arg.startsWith("--") && arg.indexOf('=') > 0) { 496 param = arg.substring(arg.indexOf('=') + 1, arg.length()); 497 } else if (i + 1 < args.length) { 498 param = args[++i]; 499 } 500 501 if (param == null || param.isEmpty() || param.charAt(0) == '-') { 502 throw new BadArgs("missing argument for option: {0}", arg).showUsage(true); 503 } 504 } 505 506 option.process(this, arg, param); 507 508 if (option.ignoreRest()) { 509 break; 510 } 511 } else { 512 options.files.add(arg); 513 } 514 } 515 } 516 517 private static Option getOption(String name) throws BadArgs { 518 for (Option o : recognizedOptions) { 519 if (o.matches(name)) { 520 return o; 521 } 522 } 523 throw new BadArgs("unknown option: {0}", name).showUsage(true); 524 } 525 526 public void printInfo(String message) { 527 if (options.info) { 528 log.print(message); 529 log.flush(); 530 } 531 } 532 533 public void printlnInfo(String message) { 534 if (options.info) { 535 log.println(message); 536 log.flush(); 537 } 538 } 539 540 public void printVerbose(String message) { 541 if (options.verbose) { 542 log.print(message); 543 log.flush(); 544 } 545 } 546 547 public void printlnVerbose(String message) { 548 if (options.verbose) { 549 log.println(message); 550 log.flush(); 551 } 552 } 553 554 public void printDebug(String message) { 555 if (options.debug) { 556 log.print(message); 557 log.flush(); 558 } 559 } 560 561 public void printlnDebug(String message) { 562 if (options.debug) { 563 log.println(message); 564 log.flush(); 565 } 566 } 567 568 public void printError(String message) { 569 log.println("Error: " + message); 570 log.flush(); 571 } 572 573 private void reportError(String key, Object... args) { 574 printError(MessageFormat.format(key, args)); 575 } 576 577 private void warning(String key, Object... args) { 578 log.println("Warning: " + MessageFormat.format(key, args)); 579 log.flush(); 580 } 581 582 private void showUsage() { 583 log.println("Usage: " + PROGNAME + " <options> list..."); 584 log.println("use --help for a list of possible options"); 585 } 586 587 private void showHelp() { 588 log.println("Usage: " + PROGNAME + " <options> <--module name> | <list...>"); 589 log.println(); 590 log.println(" list A list of class files, jar files or directories which"); 591 log.println(" contains class files."); 592 log.println(); 593 log.println("where possible options include:"); 594 for (Option o : recognizedOptions) { 595 String name = o.aliases[0].substring(1); // there must always be at least one name 596 name = name.charAt(0) == '-' ? name.substring(1) : name; 597 if (o.isHidden() || name.equals("h")) { 598 continue; 599 } 600 log.println(o.help); 601 } 602 } 603 604 private void showVersion() { 605 log.println(PROGNAME + " " + JVM_VERSION); 606 } 607 608 /** 609 * Collect all method we should compile. 610 * 611 * @return array list of AOT classes which have compiled methods. 612 */ 613 private List<AOTCompiledClass> collectMethodsToCompile(Set<Class<?>> classesToCompile, CompilationSpec compilationRestrictions, GraalFilters filters, MetaAccessProvider metaAccess) { 614 int total = 0; 615 int count = 0; 616 List<AOTCompiledClass> classes = new ArrayList<>(); 617 618 for (Class<?> c : classesToCompile) { 619 ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c); 620 if (filters.shouldCompileAnyMethodInClass(resolvedJavaType)) { 621 AOTCompiledClass aotClass = new AOTCompiledClass(resolvedJavaType); 622 printlnVerbose(" Scanning " + c.getName()); 623 624 // Constructors 625 try { 626 ResolvedJavaMethod[] ctors = resolvedJavaType.getDeclaredConstructors(); 627 addMethods(aotClass, ctors, compilationRestrictions, filters); 628 total += ctors.length; 629 } catch (Throwable e) { 630 // If we are running in JCK mode we ignore all exceptions. 631 if (options.ignoreClassLoadingErrors) { 632 printError(c.getName() + ": " + e); 633 } else { 634 throw new InternalError(e); 635 } 636 } 637 638 // Methods 639 try { 640 ResolvedJavaMethod[] methods = resolvedJavaType.getDeclaredMethods(); 641 addMethods(aotClass, methods, compilationRestrictions, filters); 642 total += methods.length; 643 } catch (Throwable e) { 644 // If we are running in JCK mode we ignore all exceptions. 645 if (options.ignoreClassLoadingErrors) { 646 printError(c.getName() + ": " + e); 647 } else { 648 throw new InternalError(e); 649 } 650 } 651 652 // Class initializer 653 try { 654 ResolvedJavaMethod clinit = resolvedJavaType.getClassInitializer(); 655 if (clinit != null) { 656 addMethod(aotClass, clinit, compilationRestrictions, filters); 657 total++; 658 } 659 } catch (Throwable e) { 660 // If we are running in JCK mode we ignore all exceptions. 661 if (options.ignoreClassLoadingErrors) { 662 printError(c.getName() + ": " + e); 663 } else { 664 throw new InternalError(e); 665 } 666 } 667 668 // Found any methods to compile? Add the class. 669 if (aotClass.hasMethods()) { 670 classes.add(aotClass); 671 count += aotClass.getMethodCount(); 672 } 673 } 674 } 675 printInfo(total + " methods total, " + count + " methods to compile"); 676 return classes; 677 } 678 679 /** 680 * If a file with compilation limitations is specified using the java property 681 * jdk.tools.jaotc.compile.method.list, read the file's contents and collect the restrictions. 682 */ 683 private CompilationSpec collectSpecifiedMethods() { 684 CompilationSpec compilationRestrictions = new CompilationSpec(); 685 String methodListFileName = options.methodList; 686 687 if (methodListFileName != null && !methodListFileName.equals("")) { 688 try { 689 FileReader methListFile = new FileReader(methodListFileName); 690 BufferedReader readBuf = new BufferedReader(methListFile); 691 String line = null; 692 while ((line = readBuf.readLine()) != null) { 693 String trimmedLine = line.trim(); 694 if (!trimmedLine.startsWith("#")) { 695 String[] components = trimmedLine.split(" "); 696 if (components.length == 2) { 697 String directive = components[0]; 698 String pattern = components[1]; 699 switch (directive) { 700 case "compileOnly": 701 compilationRestrictions.addCompileOnlyPattern(pattern); 702 break; 703 case "exclude": 704 compilationRestrictions.addExcludePattern(pattern); 705 break; 706 default: 707 System.out.println("Unrecognized command " + directive + ". Ignoring\n\t" + line + "\n encountered in " + methodListFileName); 708 } 709 } else { 710 if (!trimmedLine.equals("")) { 711 System.out.println("Ignoring malformed line:\n\t " + line + "\n"); 712 } 713 } 714 } 715 } 716 readBuf.close(); 717 } catch (FileNotFoundException e) { 718 throw new InternalError("Unable to open method list file: " + methodListFileName, e); 719 } catch (IOException e) { 720 throw new InternalError("Unable to read method list file: " + methodListFileName, e); 721 } 722 } 723 724 return compilationRestrictions; 725 } 726 727 private static void openLog() { 728 int v = Integer.getInteger("jdk.tools.jaotc.logCompilation", 0); 729 if (v == 0) { 730 logFile = null; 731 return; 732 } 733 // Create log file in current directory 734 String fileName = "aot_compilation" + new Date().getTime() + ".log"; 735 Path logFilePath = Paths.get("./", fileName); 736 String logFileName = logFilePath.toString(); 737 try { 738 // Create file to which we do not append 739 logFile = new FileWriter(logFileName, false); 740 } catch (IOException e) { 741 System.out.println("Unable to open logfile :" + logFileName + "\nNo logs will be created"); 742 logFile = null; 743 } 744 } 745 746 public static void writeLog(String str) { 747 if (logFile != null) { 748 try { 749 logFile.write(str + "\n"); 750 logFile.flush(); 751 } catch (IOException e) { 752 // Print to console 753 System.out.println(str + "\n"); 754 } 755 } 756 } 757 758 public static void closeLog() { 759 if (logFile != null) { 760 try { 761 logFile.close(); 762 } catch (IOException e) { 763 // Do nothing 764 } 765 } 766 } 767 }