2

PermGen での過剰なメモリ割り当てに関する問題があります。

このメモリ空間のサイズを監視する小さなコードを書いたところ、ほとんどのメソッドを実行するたびに、割り当てられたメモリのサイズが大きくなることに気付きました。私のアプリケーションにはグローバルオブジェクトがたくさんあるのではないでしょうか? PermGen でどのオブジェクトが割り当てられているかを知る方法はありますか? 現在、使用されているメモリのサイズしかわかりません。

これは私が書いたコードで、各メソッド呼び出しの後に実行されるアドバイスとして定義されています。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;

import java.util.Iterator;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;


@Aspect
public class PermGenStat {

    static Long bytesPrecedenti = getUsedPermGenBytes();

    private static Long getUsedPermGenBytes() {

    Long bytes = 0L;

    Iterator<MemoryPoolMXBean> iter = ManagementFactory.getMemoryPoolMXBeans().iterator();

        while (iter.hasNext()) {
            MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next();
            if (item.getName().equals("PS Perm Gen"))
                bytes = item.getUsage().getUsed();
        }

        return bytes;
    }

    @AfterReturning (pointcut = "execution(* it.xxx.yyy.*.*.*.*(..))",
                     returning = "result")

    public void afterReturning (JoinPoint joinPoint, Object result) {

        if (joinPoint != null &&
        joinPoint.getTarget() != null &&
        joinPoint.getTarget().getClass() != null &&
        joinPoint.getSignature() != null &&
        joinPoint.getSignature().getName() != null) {

        try {
            Long bytes = getUsedPermGenBytes();
            Long diff = bytes - bytesPrecedenti;

            if (diff >= 1) {    
                System.out.println("Metodo: " + joinPoint.getTarget().getClass().toString().substring(6) + "." +                                                    joinPoint.getSignature().getName().toString());

               System.out.println("PermGen (KB): " + Math.round((double)bytesPrecedenti / 1024) + " -> " +
                                                      Math.round((double)bytes / 1024) +
                                               " [" + Math.round((double)diff / 1024) + "]");
            }
            bytesPrecedenti = bytes;
    }
            catch (Exception e) {
            System.out.println("******************** Eccezione ********************");
                System.out.println("Classe: PermGenStat - Metodo: afterReturning");
                e.printStackTrace();
            }
        }
}

}

ありがとう

4

1 に答える 1

4

PermGen スペースには、主に反射データが含まれています。実行時に作成されるオブジェクトは通常、ヒープに格納されるため、オブジェクトを作成しても PermGen スペースのサイズは増加しません。

ただし (これは単なる推測です)、ランタイム ウィービングを使用するか、以前に呼び出されたことのないメソッドを呼び出すと (まだロードされていないクラスが必要になる場合があります)、JVM は追加のリフレクション データを PermGen 空間にロードする可能性があります (メソッド、クラス、織りプロセスによって作成されたプロキシ クラスなど)。これが、PermGen スペースの使用量の増加を経験する理由である可能性があります。

于 2013-08-19T07:47:05.367 に答える