假设我们有以下课程:
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
中:未使用的静态/实例方法是否在运行时占用内存?那些未使用的继承或导入方法呢?
答案 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");
}
因此,永远不会调用空方法。