src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
changeset 59226 a0f39cc47387
parent 58863 c16ac7a2eba4
equal deleted inserted replaced
59225:80e1201f6c9a 59226:a0f39cc47387
    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 }