在App Engine上使用Spring AOP会导致StackOverflowError

我们有一个在App Engine上运行并使用Spring框架的应用程序。 最近我们添加了一些基于AOP的新function。 我们决定使用@AspectJ样式,因此我们将到基于XML的配置中并实现了各自的方面。 在开发服务器上一切正常,但是,当部署到云环境时,每次初始化应用程序时都会得到java.lang.StackOverflowError

无法创建并导致错误的bean是使用@Configuration批注注释的配置类。 看来基本上任何配置bean都可能导致错误。

您可以在下面看到相应的堆栈跟踪。

 org.springframework.web.context.ContextLoader initWebApplicationContext: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'objectifyConfig' defined in URL [jar:file:/base/data/home/apps/{app-id}/8.372375422460842231/WEB-INF/lib/{app-name}-1.0-SNAPSHOT.jar!/{path-to-class}/ObjectifyConfig.class]: Initialization of bean failed; nested exception is java.lang.StackOverflowError at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548) at org.mortbay.jetty.servlet.Context.startContext(Context.java:136) at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250) at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517) at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:219) at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:194) at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:134) at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:446) at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:435) at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:442) at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:186) at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:306) at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:298) at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:439) at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251) at java.lang.Thread.run(Thread.java:724) Caused by: java.lang.StackOverflowError at java.util.concurrent.ConcurrentSkipListSet.contains(ConcurrentSkipListSet.java:214) at sun.misc.URLClassPath$LoaderSearchCursor.nextLoader(URLClassPath.java:598) at sun.misc.URLClassPath.getLoader(URLClassPath.java:365) at sun.misc.URLClassPath.findResource(URLClassPath.java:213) at java.net.URLClassLoader$2.run(URLClassLoader.java:551) at java.net.URLClassLoader$2.run(URLClassLoader.java:549) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findResource(URLClassLoader.java:548) at com.google.apphosting.runtime.security.UserClassLoader.findResource(UserClassLoader.java:723) at java.lang.ClassLoader.getResource(ClassLoader.java:1142) at com.google.apphosting.runtime.security.UserClassLoader$3.run(UserClassLoader.java:757) at com.google.apphosting.runtime.security.UserClassLoader$3.run(UserClassLoader.java:751) at java.security.AccessController.doPrivileged(Native Method) at com.google.apphosting.runtime.security.UserClassLoader.findResource(UserClassLoader.java:751) at java.lang.ClassLoader.getResource(ClassLoader.java:1142) at com.google.apphosting.runtime.security.UserClassLoader$3.run(UserClassLoader.java:757) at com.google.apphosting.runtime.security.UserClassLoader$3.run(UserClassLoader.java:751) at java.security.AccessController.doPrivileged(Native Method) at com.google.apphosting.runtime.security.UserClassLoader.findResource(UserClassLoader.java:751) at java.lang.ClassLoader.getResource(ClassLoader.java:1142) at com.google.apphosting.runtime.security.UserClassLoader$3.run(UserClassLoader.java:757) at com.google.apphosting.runtime.security.UserClassLoader$3.run(UserClassLoader.java:751) at java.security.AccessController.doPrivileged(Native Method) at com.google.apphosting.runtime.security.UserClassLoader.findResource(UserClassLoader.java:751) at java.lang.ClassLoader.getResource(ClassLoader.java:1142) ... 

更新:我将问题与示范问题的示例应用程序一起放入App Engine问题跟踪器。 请点击链接查看详细信息。

似乎问题已在App Engine版本1.9.7中修复。 在这里查看更多细节。

堆栈溢出通常表示无限循环。 使用aspectj,您可以在以下情况下使用它:

 Class Logger { @Autowired ConfigService conf; //... used for logging intercepted methods } Class ConfigServiceImpl implements ConfigService { //... this is used to retrieve config } 

如果你现在使用的aspectc表达式说: 我想记录我的configServiceImpl,那么在使用configService时你也会有无限循环:

  • 被记录器拦截
  • 在logger中注入的configservice尝试检索日志记录配置…
  • ==>该配置服务被记录器和故事重复拦截

我无法解释为什么它在您的本地设置上工作而不在应用引擎上。 或者为什么只有当你使用@Configuration但我认为你应该像这样看一个“循环依赖”的方向。

这可能是因为无限递归,或者因为你的堆栈太大了。 尝试增加堆栈大小以查看是否能解决问题(例如,使用-Xss1m )。 如果这没有帮助,那么您可能会有无限递归。 也可以看看:

Java堆栈溢出错误 – 如何在Eclipse中增加堆栈大小?