49 import org.openjdk.jmc.flightrecorder.internal.util.DataInputToolkit; 50 51 /** 52 * Provides an efficient means to read JFR data, chunk by chunk. The actual method employed will 53 * depend on whether the JFR file is available as a stream or as a file, and whether or not the data 54 * is compressed or not. 55 * <p> 56 * Each chunk will be self-contained and parsable, for example by wrapping it in a 57 * {@link ByteArrayInputStream} and using the {@link JfrLoaderToolkit}. 58 */ 59 public final class ChunkReader { 60 private static final byte[] JFR_MAGIC_BYTES = new byte[] {'F', 'L', 'R', 0}; 61 private static final int[] JFR_MAGIC = new int[] {'F', 'L', 'R', 0}; 62 private static final int ZIP_MAGIC[] = new int[] {31, 139}; 63 private static final int GZ_MAGIC[] = new int[] {31, 139}; 64 // For JDK 8 this is the size of the magic + version and offset to the meta data event. 65 // For JDK 9 and later, this it the part of the header right up to, and including, the chunk size. 66 private static final int HEADER_SIZE = DataInputToolkit.INTEGER_SIZE + 2 * DataInputToolkit.SHORT_SIZE 67 + DataInputToolkit.LONG_SIZE; 68 69 /** 70 * Chunk iterator for an uncompressed JFR file. Efficiently reads a JFR file, chunk by chunk, 71 * into memory as byte arrays by memory mapping the JFR file, finding the chunk boundaries with 72 * a minimum of parsing, and then block-transferring the byte arrays. The transfers will be done 73 * on {@link Iterator#next()}, and the resulting byte array will only be reachable for as long 74 * as it is referenced. The JFR file must not be zip or gzip compressed. 75 * <p> 76 * Note that {@link Iterator#next()} can throw {@link IllegalArgumentException} if it encounters 77 * a corrupted chunk. 78 */ 79 private static class ChunkIterator implements Iterator<byte[]> { 80 int lastChunkOffset; 81 private RandomAccessFile file; 82 private final FileChannel channel; 83 private final MappedByteBuffer buffer; 84 85 private ChunkIterator(File jfrFile) throws IOException { 86 try { 87 file = new RandomAccessFile(jfrFile, "r"); //$NON-NLS-1$ 88 channel = file.getChannel(); | 49 import org.openjdk.jmc.flightrecorder.internal.util.DataInputToolkit; 50 51 /** 52 * Provides an efficient means to read JFR data, chunk by chunk. The actual method employed will 53 * depend on whether the JFR file is available as a stream or as a file, and whether or not the data 54 * is compressed or not. 55 * <p> 56 * Each chunk will be self-contained and parsable, for example by wrapping it in a 57 * {@link ByteArrayInputStream} and using the {@link JfrLoaderToolkit}. 58 */ 59 public final class ChunkReader { 60 private static final byte[] JFR_MAGIC_BYTES = new byte[] {'F', 'L', 'R', 0}; 61 private static final int[] JFR_MAGIC = new int[] {'F', 'L', 'R', 0}; 62 private static final int ZIP_MAGIC[] = new int[] {31, 139}; 63 private static final int GZ_MAGIC[] = new int[] {31, 139}; 64 // For JDK 8 this is the size of the magic + version and offset to the meta data event. 65 // For JDK 9 and later, this it the part of the header right up to, and including, the chunk size. 66 private static final int HEADER_SIZE = DataInputToolkit.INTEGER_SIZE + 2 * DataInputToolkit.SHORT_SIZE 67 + DataInputToolkit.LONG_SIZE; 68 69 private ChunkReader() { 70 throw new UnsupportedOperationException("Not to be instantiated"); //$NON-NLS-1$ 71 } 72 73 /** 74 * Chunk iterator for an uncompressed JFR file. Efficiently reads a JFR file, chunk by chunk, 75 * into memory as byte arrays by memory mapping the JFR file, finding the chunk boundaries with 76 * a minimum of parsing, and then block-transferring the byte arrays. The transfers will be done 77 * on {@link Iterator#next()}, and the resulting byte array will only be reachable for as long 78 * as it is referenced. The JFR file must not be zip or gzip compressed. 79 * <p> 80 * Note that {@link Iterator#next()} can throw {@link IllegalArgumentException} if it encounters 81 * a corrupted chunk. 82 */ 83 private static class ChunkIterator implements Iterator<byte[]> { 84 int lastChunkOffset; 85 private RandomAccessFile file; 86 private final FileChannel channel; 87 private final MappedByteBuffer buffer; 88 89 private ChunkIterator(File jfrFile) throws IOException { 90 try { 91 file = new RandomAccessFile(jfrFile, "r"); //$NON-NLS-1$ 92 channel = file.getChannel(); |