9

CMSコレクターとメモリバーを使用してGCをトリガーするTomcatアプリケーションに取り組んでいます。Webアプリをリロードすると、古い世代がGCをトリガーするのに十分な量であるのに、死んだクラスローダーが収集されないという状況に陥ることがあります。

クラスがpermgenに割り当てられていることを読み、したがって、それらはOldgenコレクションによって無視されていたと推測しました。この理論をテストするために、次のテストクラスを作成しました。

package test;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;

/*
 JVM Options:
 -server -XX:+UseMembar -XX:+UseConcMarkSweepGC
 -XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=80
 -XX:+UseCMSInitiatingOccupancyOnly -Xms100m -Xmx100m
 -XX:PermSize=100m -XX:NewSize=10m -XX:MaxNewSize=10m
 -verbose:gc -Xloggc:gc.log  -XX:+PrintGCTimeStamps
 -XX:+PrintGCDetails
 */
public class ClassLoaderTest extends ClassLoader
{
  @Override
  protected synchronized Class<?> loadClass(String xiName, boolean xiResolve)
      throws ClassNotFoundException
  {
    if (xiName.equals("test"))
    {
      // When asked to load "test", load Example.class
      Class<?> c = Example.class;
      String className = c.getName();
      String classAsPath = className.replace('.', '/') + ".class";
      InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);
      byte[] classData = null;
      try
      {
        classData = IOUtils.toByteArray(stream);
      }
      catch (IOException e)
      {
        e.printStackTrace();
      }
      return defineClass(className, classData, 0, classData.length);
    }
    return super.loadClass(xiName, xiResolve);
  }

  public static class Example {}
  public static ClassLoaderTest classLoaderTest;

  public static void main(String[] args) throws Exception
  {
    // Allocate CL in new gen
    classLoaderTest = new ClassLoaderTest();

    // Load a class - allocated in perm gen
    classLoaderTest.loadClass("test");

    // Discard CL
    classLoaderTest = null;

    // Pause at end
    Thread.sleep(99 * 60 * 1000);
  }

  public final byte[] mMem = new byte[85 * 1024 * 1024];
}

このクラスを実行し、VisualVMを使用して出力を監視したところ、デッドクラスローダーが収集されずに複数のOldおよびYoung genコレクションが実際に発生しているため、大きなバイト配列がメモリに残っていることがわかりました。

VisualVM Visual GC

Perm Genが収集されるきっかけは何ですか?

4

1 に答える 1

4

JVMオプション「CMSPermGenSweepingEnabled」および「CMSClassUnloadingEnabled」を確認してください。(ネット上での使用については多くの議論があります。)特に、最初の議論は、ガベージコレクションの実行にPermGenを含めることを想定しています。デフォルトでは、PermGenスペースがガベージコレクションに含まれることはありません(したがって、無制限に拡張されます)。

于 2011-11-05T00:29:00.113 に答える