【问题标题】:Running out of PermGen space when using DeferredTasks in GAE 1.7.3在 GAE 1.7.3 中使用 DeferredTasks 时 PermGen 空间不足
【发布时间】:2012-10-22 12:10:21
【问题描述】:

我最近切换到了 Google App Engine Java SDK 1.7.3。从那时起,每次我将DeferredTasks 提交到任务队列时,我都会用完 PermGen 空间

  • 将应用部署到 App Engine 时不会发生这种情况。它只发生在本地。但它阻止了我的本地测试和失败的集成测试。
  • 这发生在带有 Java 6 的 MacOSX 10.7.5

    $ java -version 
    java version "1.6.0_37"
    Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
    Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
    
  • 这是我在问题发生时看到的堆栈跟踪的一部分。

    INFO: Successfully processed ../target/projectName/WEB-INF/queue.xml
    Nov 1, 2012 3:04:00 PM com.google.appengine.api.taskqueue.dev.LocalTaskQueue init
    INFO: LocalTaskQueue is initialized
    Nov 1, 2012 3:04:01 PM org.quartz.simpl.SimpleThreadPool initialize
    INFO: Job execution threads will use class loader of thread: 1255545583@qtp-1458850232-0
    Nov 1, 2012 3:04:02 PM org.quartz.core.QuartzScheduler <init>
    INFO: Quartz Scheduler v.UNKNOWN.UNKNOWN.UNKNOWN created.
    Nov 1, 2012 3:04:02 PM org.quartz.simpl.RAMJobStore initialize
    INFO: RAMJobStore initialized.
    Nov 1, 2012 3:04:02 PM org.quartz.impl.StdSchedulerFactory instantiate
    INFO: Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
    Nov 1, 2012 3:04:02 PM org.quartz.impl.StdSchedulerFactory instantiate
    INFO: Quartz scheduler version: UNKNOWN.UNKNOWN.UNKNOWN
    Nov 1, 2012 3:04:02 PM org.quartz.core.QuartzScheduler start
    INFO: Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
    Nov 1, 2012 3:04:02 PM com.google.appengine.api.taskqueue.dev.LocalTaskQueue start_
    INFO: Local task queue initialized with base url http://localhost:8083
    Exception in thread "DefaultQuartzScheduler_Worker-9" java.lang.OutOfMemoryError: PermGen space
            at java.lang.ClassLoader.defineClass1(Native Method)
            at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
            at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
            at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
            at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
            at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
            at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
            at com.google.appengine.tools.development.DevAppServerClassLoader.loadClass(DevAppServerClassLoader.java:92)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
            at com.google.appengine.api.urlfetch.URLFetchServicePb$URLFetchRequest.newBuilder(URLFetchServicePb.java:1902)
            at com.google.appengine.api.taskqueue.dev.UrlFetchJob.newFetchRequest(UrlFetchJob.java:152)
            at com.google.appengine.api.taskqueue.dev.UrlFetchJob.execute(UrlFetchJob.java:83)
            at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
            at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)
    Exception in thread "1255545583@qtp-1458850232-0" java.lang.OutOfMemoryError: PermGen space
    Exception in thread "Timer-6" java.lang.OutOfMemoryError: PermGen space
    Exception in thread "Timer-4" java.lang.OutOfMemoryError: PermGen space
    Exception in thread "Timer-2" java.lang.OutOfMemoryError: PermGen space
    Exception in thread "Timer-8" java.lang.OutOfMemoryError: PermGen space
    

有关触发问题的代码,请参见下文。 DeferredTask 有一个 memcache 引用,用于从 memcache 获取数据并可能将其删除。任务延迟 10 秒运行。

class Foo {
    private void enqueueTask() {
        queue.add(TaskOptions.Builder.withPayload(new Task()).countdownMillis(10 * 1000));
    }

    private static class Task implements DeferredTask {
        private static final MemcacheService memcache = MemcacheServiceFactory.getMemcacheService();
        private static final Logger log = Logger.getLogger(Task.class.getName());

        @Override
        public void run() {
            final String key = ...;

            if (memcache.contains(key)) {
                final Object value = memcache.get(key);

                if (some condition depending on value) {
                    memcache.delete(key);
                    memcache.increment(some other field, -1l);
                }
            } else {
                log.warning("error message");
            }
        }
    }
}

其他人可以复制吗?谢谢!

更新:我在 GAE 的 Google 代码页面上为此创建了 issue 8377

【问题讨论】:

  • 为什么不使用 XXMaxPermSize JVM arg 增加内存量?
  • 首先,我认为我的应用程序/GAE 本身出了点问题。 我没有做任何特别的事情,我想了解为什么我的 PermGen 空间不足。我实际上是在启动 GAE 并调用一个添加 DeferredTask 的 URL。 其次,我使用的是 maven-gae-plugin。并且(1)将 XXMaxPermSize 添加到 MAVEN_OPTS 和(2)将其添加到 maven-gae-plugin 的 .. 不会改变PermGen 空间的大小。由 Maven 启动以运行 GAE 的 JVM 并没有拾取这一点。
  • 在 GAE 中运行时如何增加 PermGen 空间?这甚至可能吗?
  • 您无法更改服务器上的实例配置。您只能为本地开发环境执行此操作。

标签: google-app-engine memory-leaks task-queue permgen


【解决方案1】:

此问题已在 2014 年 8 月 12 日的 1.9.6 AppEngine SDK 版本中得到解决。 MaxPermSize 只能在本地开发服务器上设置。

【讨论】:

  • MaxPermSize 只能在本地开发服务器上设置。 ,如何?
猜你喜欢
  • 2012-05-26
  • 1970-01-01
  • 2013-03-14
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
相关资源
最近更新 更多