Как уменьшить объем памяти Spring

Я хотел бы спросить вас, как (или если) можно уменьшить объем ОЗУ Spring framework.

Я создал простое приложение HelloWorld для демонстрации проблемы. Есть только два класса и контекст.xml-файл:

  • Main - класс с основным методом
  • Test - класс, используемый для моделирования некоторой " работы "(printig Hello в бесконечном цикле)

context.xml содержит только это:

<context:component-scan base-package="mypackage" />

тест класс содержит только методinit, позвонил после строительства:

@Component
public class Test{

    @PostConstruct
    public void init() {
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        System.out.println("Hello " + Thread.currentThread().getName());
                        Thread.sleep(500);
                    }
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        });
        t.start();
    } 
}

Я подготовил два сценария и в обоих из них main метод содержит только одну строку.

в первом сценарии основной метод делает это:(new Test()).init(); Приложение работает без весны и потребляет только aprox. 8 МБ оперативной памяти.

во втором случае способ содержит следующее: new ClassPathXmlApplicationContext(new String[]{"spring/context.xml"}); Таким образом, приложение инициализируется через весенний контейнер и потребляет aprox. 45МБ ОЗУ !

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

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

(история этого вопроса немного сложнее, но это для меня сейчас основная проблема.)

спасибо

1 ответов


сначала несколько вещей, которые вы, возможно, уже знаете, но важны для понимания ситуации: большая часть памяти, используемой вашей программой, -куча JVM. Куча имеет начальный размер при запуске программы. Иногда JVM запрашивает у ОС больше памяти и увеличивает размер кучи. JVM также будет выполнять сборку мусора, освобождая таким образом место в куче.

когда используемый размер кучи уменьшается, память не обязательно освобождается от JVM. oracle JVM неохотно это делает. Например, если ваша программа использует 500 МБ ОЗУ при запуске, то после того, как сборка мусора использует только 100 МБ для большей части ее выполнения, вы не можете предположить, что дополнительные 400 МБ будут возвращены вашей ОС.

кроме того, такие инструменты, как диспетчер задач windows (и я предполагаю, что unix ps) отобразит размер всей памяти, выделенной JVM, независимо от того, используется ли эта память на самом деле или не. Такие инструменты, как jvisualvm позволит вам увидеть, как именно используется память в вашей программе java, и, в частности, какое количество кучи вы фактически используете против того, сколько выделяется.


имея это в виду, я протестировал вашу программу в следующих сценариях. Обратите внимание, что это зависит от многих факторов, включая то, какой JVM вы используете, его версию и, вероятно, вашу ОС.

  • стандартный java (SE) против весны.
  • мусор collection (GC) vs none (NOGC) (я вызвал сборщик мусора из jvisualvm).
  • минимальный размер кучи, определенный для JVM (с использованием-Xmx8M). Это говорит JVM выделять только 8 МБ при запуске. По умолчанию в моей системе 256MB.

для каждого случая я сообщаю выделенный размер кучи и используемый размер кучи. Вот мои результаты:

  • SE, NOGC, 256M: 270 МБ выделено, 30 МБ используется
  • Весна, NOGC, 256M : 270 MB выделено, 30 MB используется

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

  • SE, GC, 256M: выделено 270 МБ, использовано 9 МБ

использование GC уменьшает использование кучи, но у нас все еще есть та же выделенная память

  • ЮВ, NOGC, 8М : 9 МБ выделено,
  • Весна, NOGC, 8M: 20 MB выделено,

Это самый важный результат: больше памяти выделяется, потому что Spring, вероятно, нуждается в большем в какой-то момент во время запуска.

выводы:

  • если вы пытаетесь уменьшить использование кучи, использование spring не должно быть большой проблемой. Накладные расходы не гигантские.
  • если вы пытаетесь уменьшить выделенную память, цена использования Spring в этом эксперименте более крутая. Но вы все равно можете настроить JVM так, чтобы он чаще освобождал память чем по умолчанию. Я не знаю много об этом, но параметры jvm, такие как -XX:MaxHeapFreeRatio=70 может быть началом (подробнее здесь http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning)