001/* 002 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package jdk.internal.jvmci.hotspot; 024 025import java.io.*; 026import java.lang.management.*; 027 028import jdk.internal.jvmci.options.*; 029 030/** 031 * An option that encapsulates and configures a print stream. 032 */ 033public class PrintStreamOption extends OptionValue<String> { 034 035 public PrintStreamOption() { 036 super(null); 037 } 038 039 /** 040 * The print stream to which output will be written. 041 * 042 * Declared {@code volatile} to enable safe use of double-checked locking in 043 * {@link #getStream()} and {@link #setValue(Object)}. 044 */ 045 private volatile PrintStream ps; 046 047 /** 048 * Replace any instance of %p with a an identifying name. Try to get it from the RuntimeMXBean 049 * name. 050 * 051 * @return the name of the file to log to 052 */ 053 private String getFilename() { 054 String name = getValue(); 055 if (name.contains("%p")) { 056 String runtimeName = ManagementFactory.getRuntimeMXBean().getName(); 057 try { 058 int index = runtimeName.indexOf('@'); 059 if (index != -1) { 060 long pid = Long.parseLong(runtimeName.substring(0, index)); 061 runtimeName = Long.toString(pid); 062 } 063 name = name.replaceAll("%p", runtimeName); 064 } catch (NumberFormatException e) { 065 066 } 067 } 068 return name; 069 } 070 071 /** 072 * Gets the print stream configured by this option. If no file is configured, the print stream 073 * will output to {@link CompilerToVM#writeDebugOutput(byte[], int, int)}. 074 */ 075 public PrintStream getStream() { 076 if (ps == null) { 077 if (getValue() != null) { 078 synchronized (this) { 079 if (ps == null) { 080 try { 081 final boolean enableAutoflush = true; 082 ps = new PrintStream(new FileOutputStream(getFilename()), enableAutoflush); 083 /* Add the JVM and Java arguments to the log file to help identity it. */ 084 String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments()); 085 ps.println("VM Arguments: " + inputArguments); 086 String cmd = System.getProperty("sun.java.command"); 087 if (cmd != null) { 088 ps.println("sun.java.command=" + cmd); 089 } 090 } catch (FileNotFoundException e) { 091 throw new RuntimeException("couldn't open file: " + getValue(), e); 092 } 093 } 094 } 095 } else { 096 OutputStream ttyOut = new OutputStream() { 097 CompilerToVM vm; 098 099 private CompilerToVM vm() { 100 if (vm == null) { 101 vm = HotSpotJVMCIRuntime.runtime().getCompilerToVM(); 102 } 103 return vm; 104 } 105 106 @Override 107 public void write(byte[] b, int off, int len) throws IOException { 108 if (b == null) { 109 throw new NullPointerException(); 110 } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) { 111 throw new IndexOutOfBoundsException(); 112 } else if (len == 0) { 113 return; 114 } 115 vm().writeDebugOutput(b, off, len); 116 } 117 118 @Override 119 public void write(int b) throws IOException { 120 write(new byte[]{(byte) b}, 0, 1); 121 } 122 123 @Override 124 public void flush() throws IOException { 125 vm().flushDebugOutput(); 126 } 127 }; 128 ps = new PrintStream(ttyOut); 129 } 130 } 131 return ps; 132 } 133 134 @Override 135 public void setValue(Object v) { 136 if (ps != null) { 137 synchronized (this) { 138 if (ps != null) { 139 ps.close(); 140 ps = null; 141 } 142 } 143 } 144 super.setValue(v); 145 } 146}