1 /* |
1 /* |
2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
29 import static jdk.jfr.internal.LogLevel.TRACE; |
29 import static jdk.jfr.internal.LogLevel.TRACE; |
30 import static jdk.jfr.internal.LogLevel.WARN; |
30 import static jdk.jfr.internal.LogLevel.WARN; |
31 import static jdk.jfr.internal.LogTag.JFR; |
31 import static jdk.jfr.internal.LogTag.JFR; |
32 import static jdk.jfr.internal.LogTag.JFR_SYSTEM; |
32 import static jdk.jfr.internal.LogTag.JFR_SYSTEM; |
33 |
33 |
34 import java.io.IOException; |
|
35 import java.security.AccessControlContext; |
34 import java.security.AccessControlContext; |
36 import java.security.AccessController; |
35 import java.security.AccessController; |
37 import java.time.Duration; |
36 import java.time.Duration; |
38 import java.time.Instant; |
37 import java.time.Instant; |
39 import java.util.ArrayList; |
38 import java.util.ArrayList; |
94 try { |
93 try { |
95 List<Timer> result = new CopyOnWriteArrayList<>(); |
94 List<Timer> result = new CopyOnWriteArrayList<>(); |
96 Thread t = SecuritySupport.createThreadWitNoPermissions("Permissionless thread", ()-> { |
95 Thread t = SecuritySupport.createThreadWitNoPermissions("Permissionless thread", ()-> { |
97 result.add(new Timer("JFR Recording Scheduler", true)); |
96 result.add(new Timer("JFR Recording Scheduler", true)); |
98 }); |
97 }); |
|
98 jvm.exclude(t); |
99 t.start(); |
99 t.start(); |
100 t.join(); |
100 t.join(); |
101 return result.get(0); |
101 return result.get(0); |
102 } catch (InterruptedException e) { |
102 } catch (InterruptedException e) { |
103 throw new IllegalStateException("Not able to create timer task. " + e.getMessage(), e); |
103 throw new IllegalStateException("Not able to create timer task. " + e.getMessage(), e); |
202 jvm.destroyNativeJFR(); |
202 jvm.destroyNativeJFR(); |
203 } |
203 } |
204 repository.clear(); |
204 repository.clear(); |
205 } |
205 } |
206 |
206 |
207 synchronized void start(PlatformRecording recording) { |
207 synchronized long start(PlatformRecording recording) { |
208 // State can only be NEW or DELAYED because of previous checks |
208 // State can only be NEW or DELAYED because of previous checks |
209 Instant now = Instant.now(); |
209 Instant now = Instant.now(); |
210 recording.setStartTime(now); |
210 recording.setStartTime(now); |
211 recording.updateTimer(); |
211 recording.updateTimer(); |
212 Duration duration = recording.getDuration(); |
212 Duration duration = recording.getDuration(); |
213 if (duration != null) { |
213 if (duration != null) { |
214 recording.setStopTime(now.plus(duration)); |
214 recording.setStopTime(now.plus(duration)); |
215 } |
215 } |
216 boolean toDisk = recording.isToDisk(); |
216 boolean toDisk = recording.isToDisk(); |
217 boolean beginPhysical = true; |
217 boolean beginPhysical = true; |
|
218 long streamInterval = recording.getStreamIntervalMillis(); |
218 for (PlatformRecording s : getRecordings()) { |
219 for (PlatformRecording s : getRecordings()) { |
219 if (s.getState() == RecordingState.RUNNING) { |
220 if (s.getState() == RecordingState.RUNNING) { |
220 beginPhysical = false; |
221 beginPhysical = false; |
221 if (s.isToDisk()) { |
222 if (s.isToDisk()) { |
222 toDisk = true; |
223 toDisk = true; |
223 } |
224 } |
224 } |
225 streamInterval = Math.min(streamInterval, s.getStreamIntervalMillis()); |
225 } |
226 } |
|
227 } |
|
228 long startNanos = -1; |
226 if (beginPhysical) { |
229 if (beginPhysical) { |
227 RepositoryChunk newChunk = null; |
230 RepositoryChunk newChunk = null; |
228 if (toDisk) { |
231 if (toDisk) { |
229 newChunk = repository.newChunk(now); |
232 newChunk = repository.newChunk(now); |
230 MetadataRepository.getInstance().setOutput(newChunk.getUnfishedFile().toString()); |
233 MetadataRepository.getInstance().setOutput(newChunk.getUnfishedFile().toString()); |
231 } else { |
234 } else { |
232 MetadataRepository.getInstance().setOutput(null); |
235 MetadataRepository.getInstance().setOutput(null); |
233 } |
236 } |
234 currentChunk = newChunk; |
237 currentChunk = newChunk; |
235 jvm.beginRecording_(); |
238 jvm.beginRecording_(); |
|
239 startNanos = jvm.getChunkStartNanos(); |
236 recording.setState(RecordingState.RUNNING); |
240 recording.setState(RecordingState.RUNNING); |
237 updateSettings(); |
241 updateSettings(); |
238 writeMetaEvents(); |
242 writeMetaEvents(); |
239 } else { |
243 } else { |
240 RepositoryChunk newChunk = null; |
244 RepositoryChunk newChunk = null; |
241 if (toDisk) { |
245 if (toDisk) { |
242 newChunk = repository.newChunk(now); |
246 newChunk = repository.newChunk(now); |
243 RequestEngine.doChunkEnd(); |
247 RequestEngine.doChunkEnd(); |
244 MetadataRepository.getInstance().setOutput(newChunk.getUnfishedFile().toString()); |
248 MetadataRepository.getInstance().setOutput(newChunk.getUnfishedFile().toString()); |
|
249 startNanos = jvm.getChunkStartNanos(); |
245 } |
250 } |
246 recording.setState(RecordingState.RUNNING); |
251 recording.setState(RecordingState.RUNNING); |
247 updateSettings(); |
252 updateSettings(); |
248 writeMetaEvents(); |
253 writeMetaEvents(); |
249 if (currentChunk != null) { |
254 if (currentChunk != null) { |
250 finishChunk(currentChunk, now, recording); |
255 finishChunk(currentChunk, now, recording); |
251 } |
256 } |
252 currentChunk = newChunk; |
257 currentChunk = newChunk; |
253 } |
258 } |
254 |
259 if (toDisk) { |
|
260 RequestEngine.setFlushInterval(streamInterval); |
|
261 } |
255 RequestEngine.doChunkBegin(); |
262 RequestEngine.doChunkBegin(); |
|
263 |
|
264 return startNanos; |
256 } |
265 } |
257 |
266 |
258 synchronized void stop(PlatformRecording recording) { |
267 synchronized void stop(PlatformRecording recording) { |
259 RecordingState state = recording.getState(); |
268 RecordingState state = recording.getState(); |
260 |
269 |
265 throw new IllegalStateException("Recording must be started before it can be stopped."); |
274 throw new IllegalStateException("Recording must be started before it can be stopped."); |
266 } |
275 } |
267 Instant now = Instant.now(); |
276 Instant now = Instant.now(); |
268 boolean toDisk = false; |
277 boolean toDisk = false; |
269 boolean endPhysical = true; |
278 boolean endPhysical = true; |
|
279 long streamInterval = Long.MAX_VALUE; |
270 for (PlatformRecording s : getRecordings()) { |
280 for (PlatformRecording s : getRecordings()) { |
271 RecordingState rs = s.getState(); |
281 RecordingState rs = s.getState(); |
272 if (s != recording && RecordingState.RUNNING == rs) { |
282 if (s != recording && RecordingState.RUNNING == rs) { |
273 endPhysical = false; |
283 endPhysical = false; |
274 if (s.isToDisk()) { |
284 if (s.isToDisk()) { |
275 toDisk = true; |
285 toDisk = true; |
276 } |
286 } |
|
287 streamInterval = Math.min(streamInterval, s.getStreamIntervalMillis()); |
277 } |
288 } |
278 } |
289 } |
279 OldObjectSample.emit(recording); |
290 OldObjectSample.emit(recording); |
280 |
291 |
281 if (endPhysical) { |
292 if (endPhysical) { |
307 finishChunk(currentChunk, now, null); |
318 finishChunk(currentChunk, now, null); |
308 } |
319 } |
309 currentChunk = newChunk; |
320 currentChunk = newChunk; |
310 RequestEngine.doChunkBegin(); |
321 RequestEngine.doChunkBegin(); |
311 } |
322 } |
|
323 |
|
324 if (toDisk) { |
|
325 RequestEngine.setFlushInterval(streamInterval); |
|
326 } else { |
|
327 RequestEngine.setFlushInterval(Long.MAX_VALUE); |
|
328 } |
|
329 |
312 recording.setState(RecordingState.STOPPED); |
330 recording.setState(RecordingState.STOPPED); |
313 } |
331 } |
314 |
332 |
315 private void dumpMemoryToDestination(PlatformRecording recording) { |
333 private void dumpMemoryToDestination(PlatformRecording recording) { |
316 WriteableUserPath dest = recording.getDestination(); |
334 WriteableUserPath dest = recording.getDestination(); |
413 event.maxAge = age == null ? Long.MAX_VALUE : age.toMillis(); |
432 event.maxAge = age == null ? Long.MAX_VALUE : age.toMillis(); |
414 Long size = r.getMaxSize(); |
433 Long size = r.getMaxSize(); |
415 event.maxSize = size == null ? Long.MAX_VALUE : size; |
434 event.maxSize = size == null ? Long.MAX_VALUE : size; |
416 Instant start = r.getStartTime(); |
435 Instant start = r.getStartTime(); |
417 event.recordingStart = start == null ? Long.MAX_VALUE : start.toEpochMilli(); |
436 event.recordingStart = start == null ? Long.MAX_VALUE : start.toEpochMilli(); |
|
437 Duration fi = r.getFlushInterval(); |
|
438 event.flushInterval = fi == null ? Long.MAX_VALUE : fi.toMillis(); |
418 event.commit(); |
439 event.commit(); |
419 } |
440 } |
420 } |
441 } |
421 } |
442 } |
422 if (activeSettingEvent.isEnabled()) { |
443 if (activeSettingEvent.isEnabled()) { |