33import java .io .IOException ;
44import java .lang .reflect .InvocationTargetException ;
55import java .lang .reflect .Method ;
6+ import java .nio .ByteOrder ;
7+ import java .nio .MappedByteBuffer ;
68import java .nio .channels .FileChannel ;
9+ import java .nio .file .Files ;
710import java .nio .file .Path ;
811import java .nio .file .StandardOpenOption ;
912
@@ -27,9 +30,24 @@ public class FileMapUtil {
2730 *
2831 * @throws IOException
2932 * If any I/O error occurs.
33+ * @throws IllegalStateException
34+ * If the environment is locked up and
35+ * file is larger than 2GB.
3036 */
3137 public static ByteData map (Path path ) throws IOException {
32- try (FileChannel fc = FileChannel .open (path , StandardOpenOption .READ )) {
38+ if (MAP == null ) {
39+ long size = Files .size (path );
40+ if (size <= Integer .MAX_VALUE ) {
41+ try (FileChannel fc = FileChannel .open (path , StandardOpenOption .READ )) {
42+ long length = fc .size ();
43+ MappedByteBuffer buffer = fc .map (FileChannel .MapMode .READ_ONLY , 0L , length );
44+ buffer .order (ByteOrder .LITTLE_ENDIAN );
45+ return BufferData .wrap (buffer );
46+ }
47+ }
48+ throw new IllegalStateException ("Cannot map more than 2GB of data in locked up environment" );
49+ }
50+ try (FileChannel fc = FileChannel .open (path , StandardOpenOption .READ )) {
3351 long length = fc .size ();
3452 long address ;
3553 try {
@@ -38,13 +56,13 @@ public static ByteData map(Path path) throws IOException {
3856 } else {
3957 address = (long ) MAP .invoke (fc , 0 , 0L , length , false );
4058 }
41- } catch (InvocationTargetException | IllegalAccessException ex ) {
59+ } catch (InvocationTargetException | IllegalAccessException ex ) {
4260 throw new IllegalStateException ("Could not invoke map0" , ex );
4361 }
4462 ByteData mappedFile = new UnsafeMappedFile (address , length , () -> {
4563 try {
4664 UNMAP .invoke (null , address , length );
47- } catch (IllegalAccessException | InvocationTargetException ex ) {
65+ } catch (IllegalAccessException | InvocationTargetException ex ) {
4866 throw new InternalError (ex );
4967 }
5068 });
@@ -54,23 +72,38 @@ public static ByteData map(Path path) throws IOException {
5472
5573 static {
5674 boolean oldMap = false ;
57- try {
58- Class <?> c = Class .forName ("sun.nio.ch.FileChannelImpl" );
59- Method map ;
75+ Method map = null ;
76+ Method unmap = null ;
77+ get :
78+ {
79+ Class <?> c ;
80+ try {
81+ c = Class .forName ("sun.nio.ch.FileChannelImpl" );
82+ } catch (ClassNotFoundException ignored ) {
83+ break get ;
84+ }
6085 try {
6186 map = c .getDeclaredMethod ("map0" , int .class , long .class , long .class , boolean .class );
62- } catch (NoSuchMethodException ex ) {
63- map = c .getDeclaredMethod ("map0" , int .class , long .class , long .class );
64- oldMap = true ;
87+ } catch (NoSuchMethodException ex ) {
88+ try {
89+ map = c .getDeclaredMethod ("map0" , int .class , long .class , long .class );
90+ oldMap = true ;
91+ } catch (NoSuchMethodException ignored ) {
92+ break get ;
93+ }
94+ }
95+ try {
96+ map .setAccessible (true );
97+ unmap = c .getDeclaredMethod ("unmap0" , long .class , long .class );
98+ unmap .setAccessible (true );
99+ } catch (Exception ex ) {
100+ // Locked up environment, probably threw InaccessibleObjectException
101+ map = null ;
102+ unmap = null ;
65103 }
66- map .setAccessible (true );
67- Method unmap = c .getDeclaredMethod ("unmap0" , long .class , long .class );
68- unmap .setAccessible (true );
69- MAP = map ;
70- UNMAP = unmap ;
71- OLD_MAP = oldMap ;
72- } catch (ClassNotFoundException | NoSuchMethodException ex ) {
73- throw new ExceptionInInitializerError (ex );
74104 }
105+ MAP = map ;
106+ UNMAP = unmap ;
107+ OLD_MAP = oldMap ;
75108 }
76109}
0 commit comments