有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何在java中使用Linux mincore()

在java中,如何查找驻留在文件内存中的页面

我在C库中找到了mincore(), mincore-确定页面是否驻留在内存中

如何使用java在内存中查找文件页


共 (1) 个答案

  1. # 1 楼答案

    您需要使用JNI或JNA来调用mincore。使用普通Java是不可能的

    只能在内存映射文件上使用mincore

    有一个library通过JNI实现这一点。我在为个人项目处理内存映射文件时使用了JNA。我添加JNA代码是为了给你一个更好的想法

    您可以使用nice vmtouch程序来双重检查结果

    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);
            }
        }
    }