10

假设我们有以下类:

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

4

5 回答 5

12

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

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

有人可能会争辩说,可以生成一种优化,只将方法存根存储在内存中,然后垃圾收集方法内容(如果进行调用,则会从类文件中重新获取这些内容。)但是,我不知道执行此操作的 VM,并且由于在调用此类方法时可能会在内存中获得最小的收益和在速度上进行权衡,因此很难证明其合理性。

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

于 2012-11-24T08:50:00.717 回答
3

一个类的实例使用的内存Abc不取决于有多少方法Abc

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

于 2012-11-24T09:25:04.923 回答
2

由于类在 Sun Hotspot JVM 的 PermGen 中是安全的(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");

你会看到这样的: Usage of dude is 6432 bytes

然后创建一个没有未使用方法的 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'的dude的用法是6176字节

于 2012-11-24T09:25:30.063 回答
1

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

于 2012-11-24T09:21:47.097 回答
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");
}

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

于 2012-11-26T03:00:27.237 回答