All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.coley.llzip.util.FileMapUtil Maven / Gradle / Ivy

package software.coley.llzip.util;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteOrder;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Maps large files into memory.
 *
 * @author xDark
 */
public class FileMapUtil {
	private static final Method MAP;
	private static final Method UNMAP;
	private static final boolean OLD_MAP;

	/**
	 * Maps file into memory.
	 *
	 * @param path
	 * 		Path to a file to map.
	 *
	 * @return Mapped file.
	 *
	 * @throws IOException
	 * 		If any I/O error occurs.
	 * @throws IllegalStateException
	 * 		If the environment is locked up and
	 * 		file is larger than 2GB.
	 */
	public static ByteData map(Path path) throws IOException {
		if (MAP == null) {
			long size = Files.size(path);
			if (size <= Integer.MAX_VALUE) {
				try (FileChannel fc = FileChannel.open(path, StandardOpenOption.READ)) {
					long length = fc.size();
					MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0L, length);
					buffer.order(ByteOrder.LITTLE_ENDIAN);
					return BufferData.wrap(buffer);
				}
			}
			throw new IllegalStateException("Cannot map more than 2GB of data in locked up environment");
		}
		try (FileChannel fc = FileChannel.open(path, StandardOpenOption.READ)) {
			long length = fc.size();
			long address;
			try {
				if (OLD_MAP) {
					address = (long) MAP.invoke(fc, 0, 0L, length);
				} else {
					address = (long) MAP.invoke(fc, 0, 0L, length, false);
				}
			} catch (InvocationTargetException | IllegalAccessException ex) {
				throw new IllegalStateException("Could not invoke map0", ex);
			}
			ByteData mappedFile = new UnsafeMappedFile(address, length, () -> {
				try {
					UNMAP.invoke(null, address, length);
				} catch (IllegalAccessException | InvocationTargetException ex) {
					throw new InternalError(ex);
				}
			}, new AtomicBoolean());
			return mappedFile;
		}
	}

	static {
		boolean oldMap = false;
		Method map = null;
		Method unmap = null;
		get:
		{
			Class c;
			try {
				c = Class.forName("sun.nio.ch.FileChannelImpl");
			} catch (ClassNotFoundException ignored) {
				break get;
			}
			try {
				map = c.getDeclaredMethod("map0", int.class, long.class, long.class, boolean.class);
			} catch (NoSuchMethodException ex) {
				try {
					map = c.getDeclaredMethod("map0", int.class, long.class, long.class);
					oldMap = true;
				} catch (NoSuchMethodException ignored) {
					break get;
				}
			}
			try {
				map.setAccessible(true);
				unmap = c.getDeclaredMethod("unmap0", long.class, long.class);
				unmap.setAccessible(true);
			} catch (Exception ex) {
				// Locked up environment, probably threw InaccessibleObjectException
				map = null;
				unmap = null;
			}
		}
		MAP = map;
		UNMAP = unmap;
		OLD_MAP = oldMap;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy