Где и как хранятся методы в Java?

Ответ

В Java байт-код методов хранится в области памяти JVM, называемой Metaspace (до Java 8 — PermGen).

Что хранится в Metaspace:

  • Байт-код всех загруженных классов (включая методы).
  • Метаданные классов (имена, модификаторы, информация о полях и методах).
  • Константы времени компиляции.
  • Важно: Сами выполняемые инструкции метода (байт-код) хранятся здесь, но данные для их выполнения (локальные переменные, параметры) — в стеке потока.

Ключевые особенности Metaspace:

  1. Не-куча (Non-Heap): Отделена от основной кучи (Heap).
  2. Динамический размер: В отличие от PermGen, Metaspace по умолчанию автоматически увеличивается в пределах доступной native-памяти ОС.
  3. Общая для всех потоков.

Пример и визуализация:

class Calculator {
    // Статическая переменная хранится в Metaspace (в структуре класса)
    static String OPERATOR = "+";

    // Байт-код этого метода хранится в Metaspace
    int add(int a, int b) {
        int result = a + b; // Локальные переменные a, b, result хранятся в стеке потока
        return result;
    }
}

Схема памяти JVM (упрощенно):

  • Heap: Объекты, массивы.
  • Metaspace: Классы, байт-код методов, статические поля.
  • Stack: Локальные переменные и вызовы методов.

Ответ 18+ 🔞

Давай разберём эту тему, чтобы не было, как у Герасима, — молчал, молчал, а потом «Му-му» и всё, нихуя не понятно.

Представь себе, что JVM — это такой огромный, блядь, театр. А каждый класс в твоей программе — это пьеса. Так вот, Metaspace — это, сука, архив, где лежат все тексты этих пьес, то есть байт-код твоих методов. До Java 8 этот архив назывался PermGen и был, как шкаф в хрущёвке, — маленький и тесный, постоянно всё не влезало. А сейчас Metaspace — это уже целый склад, который может расширяться, пока оперативка не кончится, ёпта.

Что конкретно там валяется:

  • Сам байт-код всех методов, которые ты написал и которые загрузились.
  • Всякая служебная хуйня про классы: их имена, кто их родители, какие у них поля и методы.
  • Константы, которые были известны ещё при компиляции.

Но! Запомни раз и навсегда, как «Муму»: байт-код метода лежит в Metaspace, а вот данные для его работы — локальные переменные, аргументы, адреса возврата — это уже в стеке потока. Это две абсолютно разные области, блядь. Не путай, а то получится, как в той истории: «Кто серит на крыше? — Муму!». Полная ерунда.

Особенности Metaspace, чтобы блеснуть умом:

  1. Не-куча (Non-Heap): Это не та куча, где объекты живут. Это отдельная, блядь, территория.
  2. Растёт как на дрожжах: В отличие от старого PermGen, который надо было вручную раздувать, Metaspace сама расширяется, пока система не скажет «ну нахуй, всё, память кончилась».
  3. Общая для всех: Все потоки в приложении смотрят в один и тот же архив с пьесами. Иначе был бы пиздец, каждый бы свою версию класса таскал.

Смотри, как это выглядит в коде:

class Calculator {
    // Эта статическая переменная — она тоже в Metaspace, в описании класса.
    static String OPERATOR = "+";

    // А вот байт-код ЭТОГО метода — он тоже в Metaspace, как инструкция.
    int add(int a, int b) {
        int result = a + b; // А вот a, b и result — это уже в стеке потока, когда метод выполняется!
        return result;
    }
}

Итоговая, блядь, схема на пальцах:

  • Heap (Куча): Тут живут объекты (new Calculator()) и массивы. Беспорядочная, шумная жизнь, сборщик мусора постоянно убирается.
  • Metaspace: Тихий архив. Лежат «чертежи» классов (байт-код) и статика.
  • Stack (Стек потока): Активная работа. Здесь методы вызываются, локальные переменные создаются и умирают. Своя зона у каждого потока.

Вот и вся магия. Главное — не делать, как тот максималист Герасим, и не пытаться всё свалить в одну кучу. Всё должно быть на своих местах: код — в Metaspace, данные — в стеке и куче. Тогда и работать будет, и память не кончится раньше времени.