Как найти метод, который вызывает небезопасные распределения? - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь найти собственную утечку памяти в моем производственном приложении. Проблема в том, чтобы узнать, какой метод в моем коде делает unsafe.allocateMemory(size) без unsafe.freeMemory(startIndex)

Это для Ubuntu 18.04, Java-версия "1.8.0_191".

// Example of "Unlimited array" 
class DirectIntArray implements Closeable {

    private final static long INT_SIZE_IN_BYTES = 4;

    private final long startIndex;

    private final Unsafe unsafe;

    public DirectIntArray(long size) throws NoSuchFieldException, IllegalAccessException {
        unsafe = getUnsafe();
        startIndex = unsafe.allocateMemory(size * INT_SIZE_IN_BYTES);
        unsafe.setMemory(startIndex, size * INT_SIZE_IN_BYTES, (byte) 0);
    }

    @Override
    public void close() throws IOException {
        unsafe.freeMemory(startIndex);
    }

    public void setValue(long index, int value) {
        unsafe.putInt(index(index), value);
    }

    public int getValue(long index) {
        return unsafe.getInt(index(index));
    }

    private long index(long offset) {
        return startIndex + offset * INT_SIZE_IN_BYTES;
    }

    private static Unsafe getUnsafe() throws IllegalAccessException, NoSuchFieldException {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        return (Unsafe) theUnsafe.get(null);
    }
} 



public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException {

        int cnt = 0;
        System.out.println("Use big array in off-heap without freeing memory");
        while (true) {
            useWithLeak(MB);
            Thread.sleep(10);
            System.out.println(++cnt + "MB Allocated");
        }
    }

    public static void useWithLeak(long len) {
        try {
            DirectIntArray arr = new DirectIntArray(len);
            arr.setValue(1, 111);
            arr.setValue(len, 222);

            System.out.println("Read from off-heap values: " +  arr.getValue(1) + ", " + arr.getValue(len));
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

Итак, я написал код, который производит утечку памяти, и я хочу найти метод, который это делает. Я использую jemalloc, и у меня есть файл .gif, который я получил в соответствии с этой инструкцией . У меня есть изображение

enter image description here

Так как я мог догадаться, что 0x00007f2e42297ea7 - это useWithLeak метод? Это реально?

...