Большинство JVM выделяют память для неиспользуемых методов?

Скажем, у нас есть следующие классы:

class DoubleOhSeven {
  public static void doSomethingClassy();
  public static void neverDoThisClassy();
}

class Dude {
  public void doSomething();
  public void neverDoThis();
}

public class Party {
  public static void main(String[] args){
    DoubleOhSeven.doSomething();
    Dude guy = new Dude;
    guy.doSomething();
  }
}

Конечно, все методы будут скомпилированы в их соответствующие .class: не используются ли неиспользуемые статические методы/экземпляры в памяти во время выполнения? Что относительно неиспользуемых унаследованных или импортированных методов?

Ответ 1

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

Если бы они были оптимизированы, то это сделало бы рефлексивные призывы к этим методам невозможным.

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

Неиспользуемые унаследованные методы будут точно такими же.

Ответ 2

Память, используемая экземпляром класса Abc, не зависит от того, сколько методов существует в Abc.

Сгенерированный байт-код, очевидно, увеличивает размер при добавлении методов, независимо от того, что они делают что-то или нет, но это повлияет только на размер объекта класса Abc.class, который загружается только один раз, независимо от того, сколько экземпляров создан.

Ответ 3

Так как классы защищены в ПерминГен для JVM Sun Hotspot (это изменится для Java 8), вы можете сделать что-то вроде этого, сначала запустить:


MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
long before = memoryMXBean.getNonHeapMemoryUsage().getUsed();
new Dude(); // class must not be loaded before
System.out.println("Usage of dude is " + (memoryMXBean.getNonHeapMemoryUsage().getUsed() - before) + " bytes");

И вы увидите что-то вроде этого: Использование чувака составляет 6432 байта.

И затем создайте класс Dude без неиспользуемого метода и запустите тест:


MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
long before = memoryMXBean.getNonHeapMemoryUsage().getUsed();
new DudeWithoutNeverDoThis(); // must not be loaded before
System.out.println("Usage of dude without 'nerverDoThis' is " + (memoryMXBean.getNonHeapMemoryUsage().getUsed() - before) + " bytes");

и вы видите разницу (использование чувака без "nerverDoThis" составляет 6176 байт)

Ответ 4

Неиспользуемые методы увеличивают размер класса, но классы хранятся в так называемой памяти PermGen. Память кучи, где хранятся обычные объекты Java, не зависит от размера класса

Ответ 5

Метод может быть скомпилирован и загружен в PerGen.

Но метод JVM может быть optimize, используя method inlining.

Например:

public class Test {

    public void foo(){
        System.out.println("foo");
        bar();
    }

    public void bar(){
        System.out.println("bar");
    }
}

Метод будет скомпилирован таким образом компилятором JIT:

public void foo(){
    System.out.println("foo");
    System.out.println("bar");
}

Таким образом, пустой метод никогда не будет вызываться.