< prev index next >

core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/internal/FlightRecordingLoader.java

Print this page




  51 import java.util.logging.Level;
  52 import java.util.logging.Logger;
  53 
  54 import org.openjdk.jmc.flightrecorder.CouldNotLoadRecordingException;
  55 import org.openjdk.jmc.flightrecorder.internal.parser.Chunk;
  56 import org.openjdk.jmc.flightrecorder.internal.parser.LoaderContext;
  57 import org.openjdk.jmc.flightrecorder.internal.parser.v0.ChunkLoaderV0;
  58 import org.openjdk.jmc.flightrecorder.internal.parser.v1.ChunkLoaderV1;
  59 import org.openjdk.jmc.flightrecorder.parser.IParserExtension;
  60 import org.openjdk.jmc.flightrecorder.parser.ParserExtensionRegistry;
  61 
  62 /**
  63  * Helper class for loading flight recordings from disk.
  64  */
  65 public final class FlightRecordingLoader {
  66 
  67         private static final Logger LOGGER = Logger.getLogger(FlightRecordingLoader.class.getName());
  68         private static final String SINGLE_THREADED_PARSER_PROPERTY_KEY = "org.openjdk.jmc.flightrecorder.parser.singlethreaded"; //$NON-NLS-1$
  69         private static final int MIN_MEMORY_PER_THREAD = 300 * 1024 * 1024; // Unless the chunks are very big, 300MB of available memory per parallel chunk load should be plenty
  70         private static final short VERSION_0 = 0; // JDK7 & JDK8
  71         private static final short VERSION_1 = 1; // JDK9

  72         private static final byte[] FLIGHT_RECORDER_MAGIC = {'F', 'L', 'R', '\0'};
  73 
  74         public static EventArray[] loadStream(InputStream stream, boolean hideExperimentals, boolean ignoreTruncatedChunk)
  75                         throws CouldNotLoadRecordingException, IOException {
  76                 return loadStream(stream, ParserExtensionRegistry.getParserExtensions(), hideExperimentals,
  77                                 ignoreTruncatedChunk);
  78         }
  79 
  80         /**
  81          * Read events from an input stream of JFR data.
  82          *
  83          * @param stream
  84          *            input stream
  85          * @param extensions
  86          *            the extensions to use when parsing the data
  87          * @param hideExperimentals
  88          *            if {@code true}, then events of types marked as experimental will be ignored when
  89          *            reading the data
  90          * @return an array of EventArrays (one event type per EventArray)
  91          */


 160                 long nextChunkPos = 0;
 161                 final List<ChunkInfo> chunks = new ArrayList<>();
 162                 byte[] buffer = new byte[0];
 163                 Chunk nextChunk;
 164                 while ((nextChunk = chunkSupplier.getNextChunk(buffer)) != null) {
 165                         ChunkInfo info = getChunkInfo(nextChunk, nextChunkPos);
 166                         nextChunk.skip(info.getChunkSize());
 167                         buffer = nextChunk.getReusableBuffer();
 168                         nextChunkPos += info.getChunkSize();
 169                         chunks.add(info);
 170                 }
 171                 return chunks;
 172         }
 173 
 174         private static ChunkInfo getChunkInfo(Chunk nextChunk, long nextChunkPos)
 175                         throws CouldNotLoadRecordingException, IOException {
 176                 switch (nextChunk.getMajorVersion()) {
 177                 case VERSION_0:
 178                         return ChunkLoaderV0.getInfo(nextChunk, nextChunkPos);
 179                 case VERSION_1:

 180                         return ChunkLoaderV1.getInfo(nextChunk, nextChunkPos);
 181                 default:
 182                         throw new VersionNotSupportedException();
 183                 }
 184         }
 185 
 186         public static EventArray[] readChunks(
 187                 Runnable monitor, IChunkSupplier chunkSupplier, boolean hideExperimentals, boolean ignoreTruncatedChunk)
 188                         throws CouldNotLoadRecordingException, IOException {
 189                 return readChunks(monitor, ParserExtensionRegistry.getParserExtensions(), chunkSupplier, hideExperimentals,
 190                                 ignoreTruncatedChunk);
 191         }
 192 
 193         public static EventArray[] readChunks(
 194                 Runnable monitor, List<? extends IParserExtension> extensions, IChunkSupplier chunkSupplier,
 195                 boolean hideExperimentals, boolean ignoreTruncatedChunk) throws CouldNotLoadRecordingException, IOException {
 196                 LoaderContext context = new LoaderContext(extensions, hideExperimentals);
 197                 Runtime rt = Runtime.getRuntime();
 198                 long availableMemory = rt.maxMemory() - rt.totalMemory() + rt.freeMemory();
 199                 long maxBuffersCount = Math.min(Math.max(availableMemory / MIN_MEMORY_PER_THREAD, 1),


 279          * @param context
 280          *            loader context that the returned chunk loader will send event data to
 281          * @param buffer
 282          *            Initial byte array to use for storing chunk data. See
 283          *            {@link IChunkSupplier#getNextChunk(byte[])}.
 284          * @param ignoreTruncatedChunk
 285          *            if true, then any exceptions caused by getting and reading the next chunk will be
 286          *            ignored and instead make the method return null
 287          * @return a new chunk loader or null if no more data is available from the chunk supplier
 288          */
 289         private static IChunkLoader createChunkLoader(
 290                 IChunkSupplier chunkSupplier, LoaderContext context, byte[] buffer, boolean ignoreTruncatedChunk)
 291                         throws CouldNotLoadRecordingException, IOException {
 292                 try {
 293                         Chunk chunk = chunkSupplier.getNextChunk(buffer);
 294                         if (chunk != null) {
 295                                 switch (chunk.getMajorVersion()) {
 296                                 case VERSION_0:
 297                                         return ChunkLoaderV0.create(chunk, context);
 298                                 case VERSION_1:

 299                                         return ChunkLoaderV1.create(chunk, context);
 300                                 default:
 301                                         throw new VersionNotSupportedException();
 302                                 }
 303                         }
 304                 } catch (IOException e) {
 305                         if (ignoreTruncatedChunk) {
 306                                 LOGGER.log(Level.INFO, "Ignoring exception while reading chunk", e); //$NON-NLS-1$
 307                         } else {
 308                                 throw e;
 309                         }
 310                 }
 311                 return null;
 312         }
 313 }


  51 import java.util.logging.Level;
  52 import java.util.logging.Logger;
  53 
  54 import org.openjdk.jmc.flightrecorder.CouldNotLoadRecordingException;
  55 import org.openjdk.jmc.flightrecorder.internal.parser.Chunk;
  56 import org.openjdk.jmc.flightrecorder.internal.parser.LoaderContext;
  57 import org.openjdk.jmc.flightrecorder.internal.parser.v0.ChunkLoaderV0;
  58 import org.openjdk.jmc.flightrecorder.internal.parser.v1.ChunkLoaderV1;
  59 import org.openjdk.jmc.flightrecorder.parser.IParserExtension;
  60 import org.openjdk.jmc.flightrecorder.parser.ParserExtensionRegistry;
  61 
  62 /**
  63  * Helper class for loading flight recordings from disk.
  64  */
  65 public final class FlightRecordingLoader {
  66 
  67         private static final Logger LOGGER = Logger.getLogger(FlightRecordingLoader.class.getName());
  68         private static final String SINGLE_THREADED_PARSER_PROPERTY_KEY = "org.openjdk.jmc.flightrecorder.parser.singlethreaded"; //$NON-NLS-1$
  69         private static final int MIN_MEMORY_PER_THREAD = 300 * 1024 * 1024; // Unless the chunks are very big, 300MB of available memory per parallel chunk load should be plenty
  70         private static final short VERSION_0 = 0; // JDK7 & JDK8
  71         private static final short VERSION_1 = 1; // JDK9 & JDK10
  72         private static final short VERSION_2 = 2; // JDK11
  73         private static final byte[] FLIGHT_RECORDER_MAGIC = {'F', 'L', 'R', '\0'};
  74 
  75         public static EventArray[] loadStream(InputStream stream, boolean hideExperimentals, boolean ignoreTruncatedChunk)
  76                         throws CouldNotLoadRecordingException, IOException {
  77                 return loadStream(stream, ParserExtensionRegistry.getParserExtensions(), hideExperimentals,
  78                                 ignoreTruncatedChunk);
  79         }
  80 
  81         /**
  82          * Read events from an input stream of JFR data.
  83          *
  84          * @param stream
  85          *            input stream
  86          * @param extensions
  87          *            the extensions to use when parsing the data
  88          * @param hideExperimentals
  89          *            if {@code true}, then events of types marked as experimental will be ignored when
  90          *            reading the data
  91          * @return an array of EventArrays (one event type per EventArray)
  92          */


 161                 long nextChunkPos = 0;
 162                 final List<ChunkInfo> chunks = new ArrayList<>();
 163                 byte[] buffer = new byte[0];
 164                 Chunk nextChunk;
 165                 while ((nextChunk = chunkSupplier.getNextChunk(buffer)) != null) {
 166                         ChunkInfo info = getChunkInfo(nextChunk, nextChunkPos);
 167                         nextChunk.skip(info.getChunkSize());
 168                         buffer = nextChunk.getReusableBuffer();
 169                         nextChunkPos += info.getChunkSize();
 170                         chunks.add(info);
 171                 }
 172                 return chunks;
 173         }
 174 
 175         private static ChunkInfo getChunkInfo(Chunk nextChunk, long nextChunkPos)
 176                         throws CouldNotLoadRecordingException, IOException {
 177                 switch (nextChunk.getMajorVersion()) {
 178                 case VERSION_0:
 179                         return ChunkLoaderV0.getInfo(nextChunk, nextChunkPos);
 180                 case VERSION_1:
 181                 case VERSION_2:
 182                         return ChunkLoaderV1.getInfo(nextChunk, nextChunkPos);
 183                 default:
 184                         throw new VersionNotSupportedException();
 185                 }
 186         }
 187 
 188         public static EventArray[] readChunks(
 189                 Runnable monitor, IChunkSupplier chunkSupplier, boolean hideExperimentals, boolean ignoreTruncatedChunk)
 190                         throws CouldNotLoadRecordingException, IOException {
 191                 return readChunks(monitor, ParserExtensionRegistry.getParserExtensions(), chunkSupplier, hideExperimentals,
 192                                 ignoreTruncatedChunk);
 193         }
 194 
 195         public static EventArray[] readChunks(
 196                 Runnable monitor, List<? extends IParserExtension> extensions, IChunkSupplier chunkSupplier,
 197                 boolean hideExperimentals, boolean ignoreTruncatedChunk) throws CouldNotLoadRecordingException, IOException {
 198                 LoaderContext context = new LoaderContext(extensions, hideExperimentals);
 199                 Runtime rt = Runtime.getRuntime();
 200                 long availableMemory = rt.maxMemory() - rt.totalMemory() + rt.freeMemory();
 201                 long maxBuffersCount = Math.min(Math.max(availableMemory / MIN_MEMORY_PER_THREAD, 1),


 281          * @param context
 282          *            loader context that the returned chunk loader will send event data to
 283          * @param buffer
 284          *            Initial byte array to use for storing chunk data. See
 285          *            {@link IChunkSupplier#getNextChunk(byte[])}.
 286          * @param ignoreTruncatedChunk
 287          *            if true, then any exceptions caused by getting and reading the next chunk will be
 288          *            ignored and instead make the method return null
 289          * @return a new chunk loader or null if no more data is available from the chunk supplier
 290          */
 291         private static IChunkLoader createChunkLoader(
 292                 IChunkSupplier chunkSupplier, LoaderContext context, byte[] buffer, boolean ignoreTruncatedChunk)
 293                         throws CouldNotLoadRecordingException, IOException {
 294                 try {
 295                         Chunk chunk = chunkSupplier.getNextChunk(buffer);
 296                         if (chunk != null) {
 297                                 switch (chunk.getMajorVersion()) {
 298                                 case VERSION_0:
 299                                         return ChunkLoaderV0.create(chunk, context);
 300                                 case VERSION_1:
 301                                 case VERSION_2:
 302                                         return ChunkLoaderV1.create(chunk, context);
 303                                 default:
 304                                         throw new VersionNotSupportedException();
 305                                 }
 306                         }
 307                 } catch (IOException e) {
 308                         if (ignoreTruncatedChunk) {
 309                                 LOGGER.log(Level.INFO, "Ignoring exception while reading chunk", e); //$NON-NLS-1$
 310                         } else {
 311                                 throw e;
 312                         }
 313                 }
 314                 return null;
 315         }
 316 }
< prev index next >