【问题标题】:Object allocation in PermGenPermGen 中的对象分配
【发布时间】:2013-08-20 22:43:14
【问题描述】:

我有一个关于 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();
            }
        }
}

}

谢谢

【问题讨论】:

  • 对象只在堆上(或者可能在栈上) 这是在 Java 7 中使用 perm gen 的代码。
  • 在 PermGen 空间中,通常只有 ClassLoader 和 Class 对象。一旦一个类第一次被使用,它应该被加载到 PermGen 中并且不再增加 PermGen。垃圾收集器算法是特定于实现的,并且 AFAIK,没有通用 API 来解决它们。你所能做的就是做一个堆转储,如果你怀疑有泄漏,比较连续的堆转储。如果您怀疑 PermGen 中存在泄漏,请在堆转储中查找 nr。加载的类,看看那里发生了什么。

标签: java permgen


【解决方案1】:

PermGen 空间主要包含反射数据。在运行时创建的对象通常存储在堆上,因此创建它们不应增加 PermGen 空间的大小。

但是(这只是一个猜测),如果您使用运行时编织或调用之前未调用过的方法(可能需要尚未加载的类),JVM 可能会将额外的反射数据加载到 PermGen 空间中(编织过程创建的方法、类、代理类等)。这可能是您体验 PermGen 空间使用量增加的原因。

【讨论】:

  • 如果多次执行相同的方法,PermGen 的大小也会增加,尽管在第一次执行期间分配的内存更多。我的项目我使用了使用反射的spring框架,也许是它在PermGen中分配了很多内存。
  • @user2572547 可能就是这种情况。您可以使用 jconsole 检查加载的类的数量。
猜你喜欢
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多