本地运行Google App Engine Java项目遇invalid CEN header错误求助
问题描述
本人较少使用Java,目前正在升级依赖库,尝试通过Maven本地运行Google App Engine Java项目时,出现如下错误:
2018-05-17 14:39:55.050:INFO:oejs.Server:main: jetty-9.3.18.v20170406 2018-05-17 14:39:55.189:WARN:oejw.WebAppContext:main: Failed startup of context c.g.a.t.d.j.DevAppEngineWebAppContext@7995092a{/,file:///Users/user1/eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/helloworld/,null}{/Users/asingh1/eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/sap_gateway} java.util.zip.ZipException: invalid CEN header (bad signature) at java.util.zip.ZipFile.open(Native Method) at java.util.zip.ZipFile.<init>(ZipFile.java:225) at java.util.zip.ZipFile.<init>(ZipFile.java:155) at java.util.jar.JarFile.<init>(JarFile.java:166) at java.util.jar.JarFile.<init>(JarFile.java:103) at sun.net.www.protocol.jar.URLJarFile.<init>(URLJarFile.java:93) at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:69) at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:84) at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:122) at sun.net.www.protocol.jar.JarURLConnection.getJarFile(JarURLConnection.java:89) at org.eclipse.jetty.webapp.MetaInfConfiguration.getTlds(MetaInfConfiguration.java:409) at org.eclipse.jetty.webapp.MetaInfConfiguration.scanForTlds(MetaInfConfiguration.java:326) at org.eclipse.jetty.webapp.MetaInfConfiguration.scanJars(MetaInfConfiguration.java:143) at org.eclipse.jetty.webapp.MetaInfConfiguration.preConfigure(MetaInfConfiguration.java:94) at org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:485) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:521) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131) at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105) at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131) at org.eclipse.jetty.server.Server.start(Server.java:422) at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105) at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61) at org.eclipse.jetty.server.Server.doStart(Server.java:389) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at com.google.appengine.tools.development.jetty9.JettyContainerService.startContainer(JettyContainerService.java:346) at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:284) at com.google.appengine.tools.development.AutomaticInstanceHolder.startUp(AutomaticInstanceHolder.java:26) at com.google.appengine.tools.development.AbstractModule.startup(AbstractModule.java:87) at com.google.appengine.tools.development.Modules.startup(Modules.java:105) at com.google.appengine.tools.development.DevAppServerImpl.doStart(DevAppServerImpl.java:274) at com.google.appengine.tools.development.DevAppServerImpl.access$000(DevAppServerImpl.java:47) at com.google.appengine.tools.development.DevAppServerImpl$1.run(DevAppServerImpl.java:219) at com.google.appengine.tools.development.DevAppServerImpl$1.run(DevAppServerImpl.java:217) at java.security.AccessController.doPrivileged(Native Method) at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:217) at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:368) at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:45) at com.google.appengine.tools.development.DevAppServerMain.run(DevAppServerMain.java:223) at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:214) 2018-05-17 14:39:55.201:INFO:oejs.AbstractConnector:main: Started NetworkTrafficSelectChannelConnector@43ee72e6{HTTP/1.1,[http/1.1]}{localhost:8080} 2018-05-17 14:39:55.212:INFO:oejs.Server:main: Started @1089ms May 17, 2018 6:39:55 PM com.google.appengine.tools.development.jetty9.JettyContainerService startHotDeployScanner INFO: 每1秒对Web应用进行一次完整扫描。
环境信息
- Java版本:jdk1.8.0_172
- Maven版本:3.5.3
- appengine.target.version:1.9.63
- maven-compiler-plugin:3.7.0(source和target版本为1.8)
- javax.servlet-api:4.0.1
已尝试的步骤
删除.m2文件夹并执行mvn clean install,但问题仍未解决,恳请各位提供帮助,谢谢!
解决方案
这个错误的核心是某个JAR包损坏或者结构异常,导致Jetty在扫描元数据时无法正常读取它。结合你的环境和已尝试的操作,推荐你按以下顺序尝试:
1. 强制更新并验证依赖完整性
你已经删除了.m2目录,但可以尝试加-U参数强制Maven更新所有依赖(包括快照版本),确保下载的JAR是完整的:
mvn clean install -U
执行完成后,手动检查本地仓库中javax.servlet-api:4.0.1和GAE相关依赖的JAR文件,用解压工具打开看看是否能正常解压,如果发现某个JAR打不开,直接删除对应目录后重新执行上面的命令。
2. 清理Jetty的临时运行目录
从错误日志可以看到,Jetty使用的临时目录是/Users/user1/eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/,这个目录里可能缓存了损坏的JAR副本,步骤如下:
- 完全停止当前运行的GAE开发服务器和Eclipse
- 删除
tmp0目录(或者整个.metadata/.plugins/org.eclipse.wst.server.core/下的所有临时文件夹) - 重新启动Eclipse并运行项目,让Jetty重新生成干净的临时文件
3. 降级Servlet API版本
GAE 1.9.63对应的Java 8环境,官方推荐的Servlet版本是3.1.0,而你使用的javax.servlet-api:4.0.1是Servlet 4.0版本,可能存在兼容性问题。修改pom.xml中的依赖:
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
然后重新执行mvn clean install再启动项目。
4. 排查依赖冲突
执行以下命令查看项目的依赖树,检查是否有多个版本的Servlet API或者Jetty相关依赖冲突:
mvn dependency:tree
如果发现冲突,比如某个依赖引入了旧版本的Servlet API,可以在对应依赖中添加排除:
<dependency> <!-- 你的依赖 --> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <version>xxx</version> <exclusions> <exclusion> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </exclusion> </exclusions> </dependency>
5. 验证GAE Maven插件配置
确保你的appengine-maven-plugin版本和appengine.target.version一致,在pom.xml中明确指定插件版本:
<build> <plugins> <plugin> <groupId>com.google.appengine</groupId> <artifactId>appengine-maven-plugin</artifactId> <version>1.9.63</version> <configuration> <target>1.9.63</target> </configuration> </plugin> </plugins> </build>
然后用mvn appengine:devserver命令启动项目,避免IDE插件的潜在问题。
内容的提问来源于stack exchange,提问作者keeterDev

