import com.sun.jna.*;
import sun.misc.Unsafe;
import sun.nio.ch.FileChannelImpl;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/**
* Example how to access mincore function from Java.
*/
public class MincoreJava {
public static void main(String[] args) throws Exception {
String file = "/tmp/foo.test";
FileChannel fc = FileChannel.open(Paths.get(file), StandardOpenOption.WRITE, StandardOpenOption.READ);
// calls mmap
MappedByteBuffer mmaped = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
// play with this to see how it changes the output
mmaped.put(10*4*1024, (byte)2);
// first lets get the address of the mmap file
// we can do this with plain Java reflection
long nativeAddress = getNativeAddressOf(mmaped);
// before we call the mincore we should get the value of system page size
// we can do this with reflection
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
int PAGE_SIZE = unsafe.pageSize();
// we need to prepare the vec array that will hold the results
// the vec must point to an array containing at least (length+PAGE_SIZE-1) / PAGE_SIZE bytes
int pages = (int) ((fc.size() + (PAGE_SIZE - 1)) / (PAGE_SIZE));
byte[] vec = new byte[pages];
// do the mincore call using JNA (we could just as well used JNI)
int result = CLibray.INSTANCE.mincore(nativeAddress, fc.size(), vec);
if (result != 0) {
throw new RuntimeException("Call to mincore failed with return value " + result);
}
// print out the pages
System.out.println("File: " + file);
System.out.println("\nOccupies " + fc.size() + " Bytes and " + pages + " Pages");
printPageInfo(nativeAddress, PAGE_SIZE, vec);
// we can call munmap via reflection
unmap(mmaped);
}
// This is the idiomatic JNA way of dealing with native code
// it is also possible to use native JNA methods
// and alternatively JNI
public interface CLibray extends Library {
CLibray INSTANCE = (CLibray) Native.loadLibrary("c", CLibray.class);
// int mincore(void *addr, size_t length, unsigned char *vec);
// JNA will automagically convert the parameters to native parameters
int mincore(long addr, long length, byte[] vec);
}
private static void printPageInfo(long baseAddress, int PAGE_SIZE, byte[] vec) {
for (int i = 0; i < vec.length; i++) {
// the least significant bit is 1 if paged
String paged = Integer.toBinaryString(vec[i]);
System.out.println(String.format("Page_%06d_[0x%s-0x%s]_%s", i,
Long.toHexString(baseAddress + i * PAGE_SIZE),
Long.toHexString(baseAddress + i * PAGE_SIZE + PAGE_SIZE - 1),
paged));
}
}
private static long getNativeAddressOf(ByteBuffer map) throws Exception {
final Field field = Buffer.class.getDeclaredField("address");
field.setAccessible(true);
return field.getLong(map);
}
public static void unmap(final MappedByteBuffer buffer) throws Exception {
if (null != buffer) {
final Method method = FileChannelImpl.class.getDeclaredMethod("unmap", MappedByteBuffer.class);
method.setAccessible(true);
method.invoke(null, buffer);
}
}
}
# 1 楼答案
您需要使用JNI或JNA来调用mincore。使用普通Java是不可能的
只能在内存映射文件上使用mincore
有一个library通过JNI实现这一点。我在为个人项目处理内存映射文件时使用了JNA。我添加JNA代码是为了给你一个更好的想法
您可以使用nice vmtouch程序来双重检查结果