Может ли Java записывать / читать из памяти кучи, которая была освобождена? - PullRequest
0 голосов
/ 19 октября 2018

Меня это удивило, я играю с Java Unsafe.В основном я тестирую:

Allocate unsafe memory -> free the memory -> Write to the freed memory

Я ожидал увидеть какую-то ошибку ошибки сегментации при доступе к памяти, которая была освобождена, но, что удивительно, ошибки / исключения не возникло.

Мой код:

protected static final Unsafe UNSAFE;
static {
    try {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        UNSAFE = (Unsafe) field.get(null);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
@Test
public void test() {
    long ptr = UNSAFE.allocateMemory(1000);
    UNSAFE.freeMemory(ptr);
    UNSAFE.putOrderedLong(null, ptr, 100L);
}

Мой вопрос: если так, то зачем нам нужна функция freeMemory() в Unsafe?Для чего это на самом деле?

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Вы получаете сигнал только в том случае, если вы либо читаете адреса, которым не была назначена страница, либо записываете в память, которая предназначена только для чтения или не назначается странице.

Когда вы выделяете небольшие области памяти, это занимаетон из собственного пула памяти, который обычно не высвобождается обратно в операционную систему при освобождении.

Если вы освобождаете память, а затем выделяете ее позже, эта память может использоваться для других целей.Продолжение использования старого адреса может привести к повреждению.

0 голосов
/ 19 октября 2018

Это может быть полностью отключено, но я все равно опубликую это.

Мне кажется, что это похоже на то, как это работает в C (как предложено @ John3136).Глядя на «официальную» документацию (http://www.docjar.com/html/api/sun/misc/Unsafe.java.html),, довольно ясно, что выделенная вами память является собственной памятью. Это означает, что она находится в памяти JVM, но в куче, выделенной для JVM самой ОС.

Когда ОС выделяет кусок памяти, она выделяет определенный диапазон адресов этой памяти, и (кроме нескольких других вещей, таких как статическая память и код), куча растет снизу, а стек сверхуадресного пространства (надеюсь, это знакомо). Так что, если в куче выделена память, и вы снова ссылаетесь на нее, нет никакого способа выйти за пределы, выделенные ОС. На самом деле, яконечно, если вы попытаетесь сделать UNSAFE.putOrderedLong(null, ptr+4, 100L), он все равно будет работать, если ваш компьютер достаточно новый. Теперь то, что хранится именно там, является загадкой даже для самой ОС, но поскольку UNSAFE работает на таком низком уровне, это определенновозможно.

...