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

生成されたバイトコードは、メソッドを追加すると、何かを実行するかどうかに関係なく、明らかにサイズが大きくなりAbc.classますが、作成されるインスタンスの数に関係なく、一度だけロードされるクラスオブジェクトのサイズにのみ影響します。

于 2012-11-24T09:25:04.923 に答える
2

クラスはSunHotspotJVMの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");

そして、あなたはこのようなものを見るでしょう: 男の使用量は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バイトです

于 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 に答える