大多数JVM是否为未使用的方法分配内存?

时间:2012-11-24 08:46:02

标签: java jvm jvm-hotspot

假设我们有以下课程:

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中:未使用的静态/实例方法是否在运行时占用内存?那些未使用的继承或导入方法呢?

5 个答案:

答案 0 :(得分:12)

未使用的方法仍然占用内存作为类/对象的一部分,即使它们没有被直接调用。

如果它们被优化掉了,那么就不可能对这些方法进行反射调用。

有人可能会争辩说,可以生成只在内存中存储方法存根的优化,并且垃圾收集方法内容(如果进行了调用,则会从类文件中重新获取。)但是,我我不知道有这样做的虚拟机,并且由于在调用这种方法时内存可能获得最小的收益和速度权衡,因此很难证明这一点。

未使用的继承方法将完全相同。

答案 1 :(得分:3)

Abc的实例使用的内存不依赖于Abc中有多少种方法。

生成的字节码在添加方法时显然会增加大小,无论它们是否执行某些操作,但这只会影响类对象Abc.class的大小,该对象只加载一次,无论有多少实例已创建。

答案 2 :(得分:2)

由于在PermGen中为Sun Hotspot JVM(将为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");

你会看到这样的事情: dude的用法是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字节

答案 3 :(得分:1)

未使用的方法会增加类的大小,但类存储在所谓的PermGen内存中。存储常规Java对象的堆内存不受类大小的影响

答案 4 :(得分:0)

该方法可以编译并加载到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");
}

因此,永远不会调用空方法。

相关问题