13

クライアント アプリケーション (Swing ベース) で非常に高い RAM 使用率に気付いたので、調査を開始しました。これは、Spring の Annotation ベースの構成に何らかの形で関連しているようです。以下の編集でわかるように、これは 64 ビット JVM でのみ発生することに気付きました。

次のテストコードを参照してください。

xml ベースの構成

<beans ....>
     <bean id="xmlConfigTest" class="at.test.XmlConfigTest" />
</beans>

public class XmlConfigTest extends JFrame {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("config/applicationContext.xml");
        XmlConfigTest frame = (XmlConfigTest) ctx.getBean("xmlConfigTest");
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

約 32MB のメモリを消費しますが、私には問題ないようです。

アノテーションベースの構成と同じになりました:

@Service
public class AnnotationConfigTestFrame extends JFrame {
    public static void main(String[] args) throws InterruptedException {
        ApplicationContext ctx = new AnnotationConfigApplicationContext("at.test");

        AnnotationConfigTestFrame frame = (AnnotationConfigTestFrame) ctx
            .getBean("annotationConfigTestFrame");
       frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
       frame.setVisible(true);
    }
}

フレームを開くのにかなり時間がかかるだけでなく、メモリ消費量が起動時に 160MB に急増し、その後約 152MB で横ばいになり、私には非常に高いように思えます。そして、これは最も基本的なケースに過ぎないことを覚えておいてください。私が開発したクライアント アプリケーションは、古いマシンには多すぎる 400MB をすでに消費しています。

誰かがこの動作について説明していますか? 理解できない..

(ここでは 3.1.1.RELEASE を使用します。)

編集 * axtavt で提案されているように、クラスパス スキャンが不要になるように、引数として Test-Class を使用して AnnotationConfigApplicationContext を直接構築しようとしました。残念ながら、メモリ消費については何も変更しませんでした。

編集 2が削除されました。編集 3 を参照してください

edit 3 32ビットと64ビットの両方のJVMと上記のテストプログラムを使用して、同じマシン(Windows 7 64ビット)でテストしました。結果は次のとおりです。

xml ベースの構成:

32-Bit JVM: 16MB
64-Bit JVM: 31MB

注釈ベースの構成:

32-Bit JVM: 17MB
64-Bit JVM: 160MB

そのため、32 ビット JVM では、両方のプログラムが近くにあり、これは私が期待することとほとんど同じです。ただし、64 ビットでは、これは異なります。最初のプログラムでさえ、64 ビットでは 2 倍のメモリを使用しますが、これはすでに多すぎるようです。それでも、64 ビットでほぼ 10 倍のメモリを使用する 2 番目のプログラムに反対するものではありません。

edit 4 ubuntuでもテストされました->同じ効果。なぜこれが起こっているのかはまだわかりません。これは私にとって本当に契約破りです

4

2 に答える 2

7

起動時に多数のjava.lang.reflect.Methodオブジェクトが作成されます。

ヒープダンプ

これらのオブジェクトはガベージ コレクションの対象となりますが、アプリケーションの場合、おそらく eden コレクションが多すぎて起動時間が長くなります。

これらのjava.lang.reflect.Methodオブジェクトのほとんどは、次のサイトに割り当てられています。

java.lang.reflect.Method オブジェクトの割り当てサイト

これらは、Spring がスーパークラスから多くのメソッドをAnnotationConfigTestFrame継承するセッターを見つけようとしたときに作成されたようです。関連するコードを詳しく読んだわけではありませんが、この仮説を検証するための簡単なテストとして、次のことを行いました。java.awtjavax.swing

@Service
public class AnnotationConfigTestFrame /* extends JFrame */
{
    public static void main(String[] args) throws InterruptedException
    {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AnnotationConfigTestFrame.class);

        AnnotationConfigTestFrame frame = (AnnotationConfigTestFrame) ctx
                .getBean("annotationConfigTestFrame");
//        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
//        frame.setVisible(true);

        waitABit();
        printRuntimeStats();
        System.exit(0);
    }
}

つまりAnnotationConfigTestFrame、 から継承しないようにしjavax.swing.JFrameます。これで、Bean を検索するためのメモリ使用量がかなり低くなりました!

これにより、これをさらにデバッグするためのヒントが得られる場合があります。

于 2012-07-23T21:40:23.800 に答える
5

を構築する方法AnnotationConfigApplicationContext(注釈付きクラスの基本パッケージを提供する)にはクラスパススキャンが必要であるため、時間とメモリがかかるのは当然です。

クラスパススキャンを回避したい場合は、対応するのコンストラクターを使用して、代わりに注釈付きクラス( @Componentsおよびs)の正確なセットを提供することを試みることができます。@ConfigurationAnnotationConfigApplicationContext

于 2012-07-19T07:23:21.747 に答える