Распределение памяти для исключения - PullRequest
6 голосов
/ 06 мая 2011

Не могли бы вы объяснить, где экземпляры Исключения или его дочерние элементы размещены в памяти?Это куча или стек, или что-то еще?

Спасибо!

Ответы [ 4 ]

3 голосов
/ 06 мая 2011

Для большинства объектов JVM все объекты создаются в куче, и исключение не является исключением.;)

JVM может размещать объекты в стеке с помощью Escape-анализа, однако это обычно ограничивается объектами, которые используются только в одном методе и не возвращаются.то есть крайне маловероятно, что исключения будут хорошим кандидатом.


Особенность метода Throwable (в том числе исключения), создаваемого во многих JVM, заключается в том, что элементы трассировки стека не создаются, пока онинеобходимы.Это потому, что большую часть времени они не нужны и их создание дорого.Однако информация для создания трассировки стека сохраняется где-то в JVM и связана с Throwable, но она не видна отладчику или отражению.

public static void main(String... args) {
    Throwable t = new Throwable("here");
    System.out.println("Throwable before getStackTrace()");
    shallowDump(t);

    System.out.println("\nThrowable after getStackTrace()");
    t.getStackTrace();
    shallowDump(t);
}

private static void shallowDump(Object pojo) {
    for (Field f : pojo.getClass().getDeclaredFields()) {
        if (Modifier.isStatic(f.getModifiers())) continue;
        f.setAccessible(true);
        Object o;
        try {
            o = f.get(pojo);
            if (o == pojo)
                o = "{self}";
            if (o instanceof Object[])
                o = "Array of "+(o.getClass().getComponentType());
        } catch (Exception e) {
            o = e;
        }
        System.out.println(f.getName() + ": " + o);
    }
}

печатает

Throwable before getStackTrace()
detailMessage: here
cause: {self}
stackTrace: null

Throwable after getStackTrace()
detailMessage: here
cause: {self}
stackTrace: Array of class java.lang.StackTraceElement

Таким образом, возникает вопрос, где хранится информация, которая использовалась для создания StackTraceElement.Глядя на код, для доступа к информации используются нативные методы.Существует загадочное поле с именем backtrace, которое нельзя увидеть с помощью отражения.

System.gc();
for (int i = 0; i < 5; i++) {
    Throwable[] ts = new Throwable[10000];
    long free = Runtime.getRuntime().freeMemory();
    for (int j = 0; j < ts.length; j++)
        ts[j] = new Throwable();
    long used = free - Runtime.getRuntime().freeMemory();
    System.out.printf("Average Throwable size was %,d%n", used / ts.length);
}
System.gc();
for (int i = 0; i < 5; i++) {
    Throwable[] ts = new Throwable[10000];
    long free = Runtime.getRuntime().freeMemory();
    for (int j = 0; j < ts.length; j++)
        ts[j] = Throwable.class.newInstance();
    long used = free - Runtime.getRuntime().freeMemory();
    System.out.printf("Average Throwable.class.newInstance() size was %,d%n", used / ts.length);
}

Получает размер Throwable, созданного в текущем методе, и Throwable, созданного в более глубоком методе с помощью отражения (более глубокий стек)

Average Throwable size was 302
Average Throwable size was 302
Average Throwable size was 302
Average Throwable size was 302
Average Throwable size was 302
Average Throwable.class.newInstance() size was 247
Average Throwable.class.newInstance() size was 296
Average Throwable.class.newInstance() size was 296
Average Throwable.class.newInstance() size was 296
Average Throwable.class.newInstance() size was 296

Размер Throwable намного больше, чем можно было бы ожидать от полей, которые он имеет.Можно предположить, что некоторая дополнительная информация хранится в куче, чтобы помочь этому классу, однако, если вся информация была сохранена в объекте Throwable, вы ожидаете, что второй тип Throwable будет больше.

0 голосов
/ 06 мая 2011

Exception с (и все Throwable с), как и любой другой тип Java-объекта. Поэтому они появятся в куче. Как указал MusiKk, в стеке могут храниться только примитивные значения или ссылки на объекты.

0 голосов
/ 06 мая 2011

Они создаются в куче, но почему это важно?

0 голосов
/ 06 мая 2011

Все объекты в Java по умолчанию размещены в куче.Вы можете специально сказать это об экземплярах Exception, потому что они обычно передаются вызывающему методу, поэтому они не могут быть в стеке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...