36
37 import org.graalvm.compiler.core.common.SuppressFBWarnings;
38 import org.graalvm.compiler.debug.TTYStreamProvider;
39 import org.graalvm.compiler.options.Option;
40 import org.graalvm.compiler.options.OptionKey;
41 import org.graalvm.compiler.options.OptionType;
42 import org.graalvm.compiler.serviceprovider.GraalServices;
43 import org.graalvm.compiler.serviceprovider.ServiceProvider;
44
45 import jdk.vm.ci.common.NativeImageReinitialize;
46 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
47 import jdk.vm.ci.services.Services;
48
49 @ServiceProvider(TTYStreamProvider.class)
50 public class HotSpotTTYStreamProvider implements TTYStreamProvider {
51
52 public static class Options {
53
54 // @formatter:off
55 @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying " +
56 "the process, usually the process id and %t will be replaced by System.currentTimeMillis().", type = OptionType.Expert)
57 public static final LogStreamOptionKey LogFile = new LogStreamOptionKey();
58 // @formatter:on
59 }
60
61 @Override
62 public PrintStream getStream() {
63 return Options.LogFile.getStream();
64 }
65
66 /**
67 * An option for a configurable file name that can also open a {@link PrintStream} on the file.
68 * If no value is given for the option, the stream will output to HotSpot's
69 * {@link HotSpotJVMCIRuntime#getLogStream() log} stream
70 */
71 private static class LogStreamOptionKey extends OptionKey<String> {
72
73 LogStreamOptionKey() {
74 super(null);
75 }
76
77 /**
78 * @return {@code nameTemplate} with all instances of %p replaced by
79 * {@link GraalServices#getExecutionID()} and %t by
80 * {@link System#currentTimeMillis()}
81 */
82 private static String makeFilename(String nameTemplate) {
83 String name = nameTemplate;
84 if (name.contains("%p")) {
85 name = name.replaceAll("%p", GraalServices.getExecutionID());
86 }
87 if (name.contains("%t")) {
88 name = name.replaceAll("%t", String.valueOf(System.currentTimeMillis()));
89 }
90 return name;
91 }
92
93 /**
94 * An output stream that redirects to {@link HotSpotJVMCIRuntime#getLogStream()}. The
95 * {@link HotSpotJVMCIRuntime#getLogStream()} value is only accessed the first time an IO
96 * operation is performed on the stream. This is required to break a deadlock in early JVMCI
97 * initialization.
98 */
99 class DelayedOutputStream extends OutputStream {
100 @NativeImageReinitialize private volatile OutputStream lazy;
101
102 private OutputStream lazy() {
103 if (lazy == null) {
104 synchronized (this) {
105 if (lazy == null) {
106 String nameTemplate = LogStreamOptionKey.this.getValue(defaultOptions());
107 if (nameTemplate != null) {
108 String name = makeFilename(nameTemplate);
109 try {
110 final boolean enableAutoflush = true;
111 FileOutputStream result = new FileOutputStream(name);
112 if (!Services.IS_IN_NATIVE_IMAGE) {
113 printVMConfig(enableAutoflush, result);
114 } else {
115 // There are no VM arguments for the libgraal library.
116 }
117 lazy = result;
118 return lazy;
119 } catch (FileNotFoundException e) {
120 throw new RuntimeException("couldn't open file: " + name, e);
121 }
122 }
123
124 lazy = HotSpotJVMCIRuntime.runtime().getLogStream();
125 PrintStream ps = new PrintStream(lazy);
126 ps.printf("[Use -D%sLogFile=<path> to redirect Graal log output to a file.]%n", GRAAL_OPTION_PROPERTY_PREFIX);
127 ps.flush();
128 }
129 }
130 }
131 return lazy;
132 }
133
134 @SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "false positive on dead store to `ps`")
135 private void printVMConfig(final boolean enableAutoflush, FileOutputStream result) {
136 /*
137 * Add the JVM and Java arguments to the log file to help identity it.
138 */
139 PrintStream ps = new PrintStream(result, enableAutoflush);
140 List<String> inputArguments = GraalServices.getInputArguments();
141 if (inputArguments != null) {
|
36
37 import org.graalvm.compiler.core.common.SuppressFBWarnings;
38 import org.graalvm.compiler.debug.TTYStreamProvider;
39 import org.graalvm.compiler.options.Option;
40 import org.graalvm.compiler.options.OptionKey;
41 import org.graalvm.compiler.options.OptionType;
42 import org.graalvm.compiler.serviceprovider.GraalServices;
43 import org.graalvm.compiler.serviceprovider.ServiceProvider;
44
45 import jdk.vm.ci.common.NativeImageReinitialize;
46 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
47 import jdk.vm.ci.services.Services;
48
49 @ServiceProvider(TTYStreamProvider.class)
50 public class HotSpotTTYStreamProvider implements TTYStreamProvider {
51
52 public static class Options {
53
54 // @formatter:off
55 @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying " +
56 "the process, usually the process id and %t will be replaced by System.currentTimeMillis(). " +
57 "Using %o as filename sends logging to System.out whereas %e sends logging to System.err.", type = OptionType.Expert)
58 public static final LogStreamOptionKey LogFile = new LogStreamOptionKey();
59 // @formatter:on
60 }
61
62 @Override
63 public PrintStream getStream() {
64 return Options.LogFile.getStream();
65 }
66
67 /**
68 * An option for a configurable file name that can also open a {@link PrintStream} on the file.
69 * If no value is given for the option, the stream will output to HotSpot's
70 * {@link HotSpotJVMCIRuntime#getLogStream() log} stream
71 */
72 private static class LogStreamOptionKey extends OptionKey<String> {
73
74 LogStreamOptionKey() {
75 super(null);
76 }
77
78 /**
79 * @return {@code nameTemplate} with all instances of %p replaced by
80 * {@link GraalServices#getExecutionID()} and %t by
81 * {@link System#currentTimeMillis()}. Checks %o and %e are not combined with any
82 * other characters.
83 */
84 private static String makeFilename(String nameTemplate) {
85 String name = nameTemplate;
86 if (name.contains("%p")) {
87 name = name.replaceAll("%p", GraalServices.getExecutionID());
88 }
89 if (name.contains("%t")) {
90 name = name.replaceAll("%t", String.valueOf(System.currentTimeMillis()));
91 }
92
93 for (String subst : new String[]{"%o", "%e"}) {
94 if (name.contains(subst) && !name.equals(subst)) {
95 throw new IllegalArgumentException("LogFile substitution " + subst + " cannot be combined with any other characters");
96 }
97 }
98
99 return name;
100 }
101
102 /**
103 * An output stream that redirects to {@link HotSpotJVMCIRuntime#getLogStream()}. The
104 * {@link HotSpotJVMCIRuntime#getLogStream()} value is only accessed the first time an IO
105 * operation is performed on the stream. This is required to break a deadlock in early JVMCI
106 * initialization.
107 */
108 class DelayedOutputStream extends OutputStream {
109 @NativeImageReinitialize private volatile OutputStream lazy;
110
111 private OutputStream lazy() {
112 if (lazy == null) {
113 synchronized (this) {
114 if (lazy == null) {
115 String nameTemplate = LogStreamOptionKey.this.getValue(defaultOptions());
116 if (nameTemplate != null) {
117 String name = makeFilename(nameTemplate);
118 switch (name) {
119 case "%o":
120 lazy = System.out;
121 break;
122 case "%e":
123 lazy = System.err;
124 break;
125 default:
126 try {
127 final boolean enableAutoflush = true;
128 FileOutputStream result = new FileOutputStream(name);
129 if (!Services.IS_IN_NATIVE_IMAGE) {
130 printVMConfig(enableAutoflush, result);
131 } else {
132 // There are no VM arguments for the libgraal
133 // library.
134 }
135 lazy = result;
136 } catch (FileNotFoundException e) {
137 throw new RuntimeException("couldn't open file: " + name, e);
138 }
139 }
140 return lazy;
141 }
142
143 lazy = HotSpotJVMCIRuntime.runtime().getLogStream();
144 PrintStream ps = new PrintStream(lazy);
145 ps.printf("[Use -D%sLogFile=<path> to redirect Graal log output to a file.]%n", GRAAL_OPTION_PROPERTY_PREFIX);
146 ps.flush();
147 }
148 }
149 }
150 return lazy;
151 }
152
153 @SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "false positive on dead store to `ps`")
154 private void printVMConfig(final boolean enableAutoflush, FileOutputStream result) {
155 /*
156 * Add the JVM and Java arguments to the log file to help identity it.
157 */
158 PrintStream ps = new PrintStream(result, enableAutoflush);
159 List<String> inputArguments = GraalServices.getInputArguments();
160 if (inputArguments != null) {
|