google-app-engine – 在GAE 1.7.3中使用DeferredTask时,运行PermGen空间

我最近切换到Google App Engine Java SDK 1.7.3。从那时起,每当我将DeferredTasks提交到任务队列中时,我已经用尽PermGen空间。

>应用程式部署到App Engine时,不会发生这种情况。它只发生在本地。但是它阻止了我的本地测试和失败的集成测试。
>它正在MacOSX 10.7.5与Java 6发生

$ 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

这是在2014年8月12日在1.9.6 AppEngine SDK版本中解决的。
MaxPermSize只能在本地的dev服务器上设置。
http://stackoverflow.com/questions/13184983/running-out-of-permgen-space-when-using-deferredtasks-in-gae-1-7-3

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:google-app-engine – 在GAE 1.7.3中使用DeferredTask时,运行PermGen空间