equal
deleted
inserted
replaced
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; |
34 import java.security.AccessControlContext; |
35 import java.security.AccessControlContext; |
35 import java.security.AccessController; |
36 import java.security.AccessController; |
36 import java.time.Duration; |
37 import java.time.Duration; |
37 import java.time.Instant; |
38 import java.time.Instant; |
38 import java.util.ArrayList; |
39 import java.util.ArrayList; |
51 import jdk.jfr.FlightRecorderListener; |
52 import jdk.jfr.FlightRecorderListener; |
52 import jdk.jfr.Recording; |
53 import jdk.jfr.Recording; |
53 import jdk.jfr.RecordingState; |
54 import jdk.jfr.RecordingState; |
54 import jdk.jfr.events.ActiveRecordingEvent; |
55 import jdk.jfr.events.ActiveRecordingEvent; |
55 import jdk.jfr.events.ActiveSettingEvent; |
56 import jdk.jfr.events.ActiveSettingEvent; |
|
57 import jdk.jfr.internal.SecuritySupport.SafePath; |
56 import jdk.jfr.internal.SecuritySupport.SecureRecorderListener; |
58 import jdk.jfr.internal.SecuritySupport.SecureRecorderListener; |
57 import jdk.jfr.internal.instrument.JDKEvents; |
59 import jdk.jfr.internal.instrument.JDKEvents; |
58 |
60 |
59 public final class PlatformRecorder { |
61 public final class PlatformRecorder { |
60 |
62 |
68 private final EventType activeSettingEvent; |
70 private final EventType activeSettingEvent; |
69 private final Thread shutdownHook; |
71 private final Thread shutdownHook; |
70 |
72 |
71 private long recordingCounter = 0; |
73 private long recordingCounter = 0; |
72 private RepositoryChunk currentChunk; |
74 private RepositoryChunk currentChunk; |
|
75 private boolean inShutdown; |
73 |
76 |
74 public PlatformRecorder() throws Exception { |
77 public PlatformRecorder() throws Exception { |
75 repository = Repository.getRepository(); |
78 repository = Repository.getRepository(); |
76 Logger.log(JFR_SYSTEM, INFO, "Initialized disk repository"); |
79 Logger.log(JFR_SYSTEM, INFO, "Initialized disk repository"); |
77 repository.ensureRepository(); |
80 repository.ensureRepository(); |
174 for (FlightRecorderListener r : getListeners()) { |
177 for (FlightRecorderListener r : getListeners()) { |
175 r.recorderInitialized(recorder); |
178 r.recorderInitialized(recorder); |
176 } |
179 } |
177 } |
180 } |
178 |
181 |
|
182 synchronized void setInShutDown() { |
|
183 this.inShutdown = true; |
|
184 } |
|
185 |
179 // called by shutdown hook |
186 // called by shutdown hook |
180 synchronized void destroy() { |
187 synchronized void destroy() { |
181 try { |
188 try { |
182 timer.cancel(); |
189 timer.cancel(); |
183 } catch (Exception ex) { |
190 } catch (Exception ex) { |
196 |
203 |
197 JDKEvents.remove(); |
204 JDKEvents.remove(); |
198 |
205 |
199 if (jvm.hasNativeJFR()) { |
206 if (jvm.hasNativeJFR()) { |
200 if (jvm.isRecording()) { |
207 if (jvm.isRecording()) { |
201 jvm.endRecording_(); |
208 jvm.endRecording(); |
202 } |
209 } |
203 jvm.destroyNativeJFR(); |
210 jvm.destroyNativeJFR(); |
204 } |
211 } |
205 repository.clear(); |
212 repository.clear(); |
206 } |
213 } |
234 MetadataRepository.getInstance().setOutput(newChunk.getUnfishedFile().toString()); |
241 MetadataRepository.getInstance().setOutput(newChunk.getUnfishedFile().toString()); |
235 } else { |
242 } else { |
236 MetadataRepository.getInstance().setOutput(null); |
243 MetadataRepository.getInstance().setOutput(null); |
237 } |
244 } |
238 currentChunk = newChunk; |
245 currentChunk = newChunk; |
239 jvm.beginRecording_(); |
246 jvm.beginRecording(); |
240 startNanos = jvm.getChunkStartNanos(); |
247 startNanos = jvm.getChunkStartNanos(); |
241 recording.setState(RecordingState.RUNNING); |
248 recording.setState(RecordingState.RUNNING); |
242 updateSettings(); |
249 updateSettings(); |
243 writeMetaEvents(); |
250 writeMetaEvents(); |
244 } else { |
251 } else { |
287 } |
294 } |
288 streamInterval = Math.min(streamInterval, s.getStreamIntervalMillis()); |
295 streamInterval = Math.min(streamInterval, s.getStreamIntervalMillis()); |
289 } |
296 } |
290 } |
297 } |
291 OldObjectSample.emit(recording); |
298 OldObjectSample.emit(recording); |
|
299 recording.setFinalStartnanos(jvm.getChunkStartNanos()); |
292 |
300 |
293 if (endPhysical) { |
301 if (endPhysical) { |
294 RequestEngine.doChunkEnd(); |
302 RequestEngine.doChunkEnd(); |
295 if (recording.isToDisk()) { |
303 if (recording.isToDisk()) { |
296 if (currentChunk != null) { |
304 if (currentChunk != null) { |
|
305 if (inShutdown) { |
|
306 jvm.markChunkFinal(); |
|
307 } |
297 MetadataRepository.getInstance().setOutput(null); |
308 MetadataRepository.getInstance().setOutput(null); |
298 finishChunk(currentChunk, now, null); |
309 finishChunk(currentChunk, now, null); |
299 currentChunk = null; |
310 currentChunk = null; |
300 } |
311 } |
301 } else { |
312 } else { |
302 // last memory |
313 // last memory |
303 dumpMemoryToDestination(recording); |
314 dumpMemoryToDestination(recording); |
304 } |
315 } |
305 jvm.endRecording_(); |
316 jvm.endRecording(); |
306 disableEvents(); |
317 disableEvents(); |
307 } else { |
318 } else { |
308 RepositoryChunk newChunk = null; |
319 RepositoryChunk newChunk = null; |
309 RequestEngine.doChunkEnd(); |
320 RequestEngine.doChunkEnd(); |
310 updateSettingsButIgnoreRecording(recording); |
321 updateSettingsButIgnoreRecording(recording); |
325 if (toDisk) { |
336 if (toDisk) { |
326 RequestEngine.setFlushInterval(streamInterval); |
337 RequestEngine.setFlushInterval(streamInterval); |
327 } else { |
338 } else { |
328 RequestEngine.setFlushInterval(Long.MAX_VALUE); |
339 RequestEngine.setFlushInterval(Long.MAX_VALUE); |
329 } |
340 } |
330 |
|
331 recording.setState(RecordingState.STOPPED); |
341 recording.setState(RecordingState.STOPPED); |
332 } |
342 } |
333 |
343 |
334 private void dumpMemoryToDestination(PlatformRecording recording) { |
344 private void dumpMemoryToDestination(PlatformRecording recording) { |
335 WriteableUserPath dest = recording.getDestination(); |
345 WriteableUserPath dest = recording.getDestination(); |
355 } |
365 } |
356 } |
366 } |
357 MetadataRepository.getInstance().setSettings(list); |
367 MetadataRepository.getInstance().setSettings(list); |
358 } |
368 } |
359 |
369 |
360 public synchronized void rotateIfRecordingToDisk() { |
370 |
361 boolean disk = false; |
|
362 for (PlatformRecording s : getRecordings()) { |
|
363 if (RecordingState.RUNNING == s.getState() && s.isToDisk()) { |
|
364 disk = true; |
|
365 } |
|
366 } |
|
367 if (disk) { |
|
368 rotateDisk(); |
|
369 } |
|
370 } |
|
371 |
371 |
372 synchronized void rotateDisk() { |
372 synchronized void rotateDisk() { |
373 Instant now = Instant.now(); |
373 Instant now = Instant.now(); |
374 RepositoryChunk newChunk = repository.newChunk(now); |
374 RepositoryChunk newChunk = repository.newChunk(now); |
375 RequestEngine.doChunkEnd(); |
375 RequestEngine.doChunkEnd(); |
582 target.setStartTime(startTime); |
582 target.setStartTime(startTime); |
583 target.setStopTime(endTime); |
583 target.setStopTime(endTime); |
584 target.setInternalDuration(Duration.between(startTime, endTime)); |
584 target.setInternalDuration(Duration.between(startTime, endTime)); |
585 } |
585 } |
586 |
586 |
587 |
587 public synchronized void migrate(SafePath repo) throws IOException { |
588 |
588 // Must set repository while holding recorder lock so |
|
589 // the final chunk in repository gets marked correctly |
|
590 Repository.getRepository().setBasePath(repo); |
|
591 boolean disk = false; |
|
592 for (PlatformRecording s : getRecordings()) { |
|
593 if (RecordingState.RUNNING == s.getState() && s.isToDisk()) { |
|
594 disk = true; |
|
595 } |
|
596 } |
|
597 if (disk) { |
|
598 jvm.markChunkFinal(); |
|
599 rotateDisk(); |
|
600 } |
|
601 } |
589 } |
602 } |