Ich habe das Verhalten bei der Dateizuordnung in Java untersucht und werde es daher zusammenfassen.
Umgebung CentOS7.3.1611, openjdk-1.8.0.131
Sie können den Systemaufruf open + mMap in der Sprache C verwenden, um Dateien dem Speicher zuzuordnen, aber ich war immer besorgt darüber, ihn in Java zu verwenden. Ich werde es tatsächlich versuchen.
Bewerten Sie mit den folgenden Quellen.
mmap01.java
import java.lang.Thread;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class mmap01
{
public static void main(String[] args) throws Exception
{
for (int argc = 0; argc < args.length; argc++ ) {
File file = new File(args[argc]);
long length = file.length();
System.out.println("file:" + args[0] + " size:" + length);
MappedByteBuffer in = new RandomAccessFile(file, "r")
.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, length);
for (long i = 0; i < length; i++) {
in.get();
}
System.out.println("Finished reading");
}
System.out.println("wait");
Thread.sleep(1000000);
}
}
Übrigens tritt im Fall einer Datei, die Integer.MAX_VALUE (2 ^ 31) überschreitet, der folgende Fehler zum Zeitpunkt der Zuordnung auf. Ich konnte mit einer Größe von 2 ^ 31-1 abbilden.
$ dd if=/dev/zero of=2gb bs=1 seek=2147483647 count=1
$ dd if=/dev/zero of=2gb-1 bs=1 seek=2147483646 count=1
$ dd if=/dev/zero of=2gb-2 bs=1 seek=2147483645 count=1
$ java mmap01 2gb
file:2gb size:2147483648
Exception in thread "main" java.lang.IllegalArgumentException: Size exceeds Integer.MAX_VALUE
at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:869)
at mmap01.main(mmap01.java:17)
$ java mmap01 2gb-1
file:2gb-1 size:2147483647
Finished reading
wait
Zu diesem Zeitpunkt sind der Speicherzuordnungsstatus des Java-Prozesses und der Java-Status wie folgt. Es scheint mit mmap abgebildet zu sein. Aus den jstat-Ergebnissen geht hervor, dass sich der zugeordnete Bereich außerhalb des Heaps befindet.
$ cat /proc/$(pidof java)/maps
(Abkürzung)
7f97c8000000-7f9848000000 r--s 00000000 00:26 5 /mnt/hgfs/COMMON/Java_Mmap/2gb-1
(Abkürzung)
$ jstat -gc $(pidof java)
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 671.9 20480.0 0.0 4480.0 866.3 384.0 73.9 0 0.000 0 0.000 0.000
$ java mmap01 2gb-1 2gb-2
file:2gb-1 size:2147483647
Finished reading
file:2gb-1 size:2147483646
Finished reading
wait
Beide Dateien sind ordnungsgemäß zugeordnet. Der Heap hat sich nicht so stark vergrößert wie der Bereich (2 ^ 31-2), der zusätzlich gelesen wurde.
$ cat /proc/$(pidof java)/maps
(Abkürzung)
7fd08c000000-7fd10c000000 r--s 00000000 00:26 6 /mnt/hgfs/COMMON/Java_Mmap/2gb-2
7fd10c000000-7fd18c000000 r--s 00000000 00:26 5 /mnt/hgfs/COMMON/Java_Mmap/2gb-1
(Abkürzung)
$ jstat -gc $(pidof java)
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 835.7 20480.0 0.0 4480.0 866.3 384.0 73.9 0 0.000 0 0.000 0.000
Warum haben wir dennoch ein Limit von 2 GB für das kartierbare Gebiet festgelegt? Es ist auch schwierig zu handhaben, da es keine explizite Methode zum Aufheben der Zuordnung gibt. Hinweise zum DirectByteBuffer- und Leistungsvergleich enthält auch eine Beschreibung der Version.
Recommended Posts