You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java17迁移后App Engine中Datastore查询报ApiProxy$CallNotFoundException

App Engine Java 17迁移:Datastore访问触发线程权限错误

问题描述

将App Engine上的Web应用从Java 8迁移至Java 17,应用使用Jakarta Servlet并打包为fat jar。Java 8环境下一切正常,但在Java 17中,仅执行简单的Datastore.get()方法时就会触发Google内部API错误,提示线程权限问题,且未自行创建任何线程。

错误栈

com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call datastore_v3.Get in a thread that is neither the original request thread nor a thread created by ThreadManager
        at com.google.apphosting.api.ApiProxy$CallNotFoundException.foreignThread(ApiProxy.java:855)
        at com.google.apphosting.api.ApiProxy$1.get(ApiProxy.java:183)
        at com.google.apphosting.api.ApiProxy$1.get(ApiProxy.java:180)
        at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:107)
        at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl$5.getFutureWithOptionalTimeout(AsyncDatastoreServiceImpl.java:361)
        at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl$5.aggregate(AsyncDatastoreServiceImpl.java:330)
        at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl$5.get(AsyncDatastoreServiceImpl.java:291)
        at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl$5.get(AsyncDatastoreServiceImpl.java:280)
        at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:107)
        at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:107)
        at com.google.appengine.api.datastore.FutureHelper.getInternal(FutureHelper.java:83)
        at com.google.appengine.api.datastore.FutureHelper.quietGet(FutureHelper.java:70)
        at com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:55)

依赖配置

<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>

<maven.clean.plugin.version>3.3.1</maven.clean.plugin.version>
<maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
<maven.dependency.plugin.version>3.6.0</maven.dependency.plugin.version>
<maven.deploy.plugin.version>3.1.1</maven.deploy.plugin.version>
<maven.enforcer.plugin.version>3.4.0</maven.enforcer.plugin.version>
<maven.install.plugin.version>3.1.1</maven.install.plugin.version>
<maven.shade.plugin.version>3.5.1</maven.shade.plugin.version>
<maven.jar.plugin.version>3.3.0</maven.jar.plugin.version>
<maven.war.plugin.version>3.4.0</maven.war.plugin.version>
<maven.javadoc.plugin.version>3.5.0</maven.javadoc.plugin.version>
<maven.resources.plugin.version>3.3.1</maven.resources.plugin.version>
<maven.source.plugin.version>3.3.0</maven.source.plugin.version>
<maven.surefire.plugin.version>3.1.2</maven.surefire.plugin.version>
<exec.plugin.version>3.1.1</exec.plugin.version>
<license.plugin.version>4.2</license.plugin.version>

<jetty.version>11.0.15</jetty.version>
<tomcat.version>10.1.18</tomcat.version>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>${tomcat.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <version>${tomcat.version}</version>
</dependency>
<dependency>
  <groupId>com.google.cloud</groupId>
  <artifactId>google-cloud-storage</artifactId>
  <version>2.31.0</version>
</dependency>
<dependency>
    <groupId>com.google.appengine.tools</groupId>
    <artifactId>appengine-gcs-client</artifactId>
    <version>0.8.3</version>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-datastore</artifactId>
    <version>2.17.3</version>
</dependency>

排查方向与解决方案

1. 升级Datastore客户端版本

当前使用的google-cloud-datastore2.17.3版本可能存在Java 17兼容性问题,建议升级到2.x系列的最新稳定版。新版本通常修复了线程上下文传递、模块化适配等Java 17相关问题。

2. 规范线程创建方式

App Engine Java 17 runtime对线程上下文的管理比Java 8更严格,即使未手动创建线程,Tomcat内部线程池(如异步Servlet线程)可能未被App Engine的ThreadManager管理:

  • 如果使用异步Servlet,必须通过ThreadManager.createThreadForCurrentRequest()创建任务线程,而非直接使用Tomcat默认线程池。
  • 检查依赖库在Java 17下的线程创建逻辑,避免第三方库创建的线程脱离App Engine上下文。

3. 解决Fat Jar依赖冲突

Fat Jar打包可能引入冲突的App Engine API依赖,导致类加载异常或上下文传递失败:

  • 排除旧版appengine-api-*间接依赖,确保仅使用google-cloud-datastore提供的客户端实现。
  • 配置Maven Shade插件的relocations规则,隔离冲突包(如com.google.appengine.api相关类),避免类版本冲突。

4. 验证Tomcat线程上下文传递

Tomcat 10.1.18兼容Jakarta Servlet 6.0,但需确认线程上下文是否正确传递给App Engine API:

  • 临时禁用异步处理,改用同步请求测试,看是否还会触发错误。
  • 检查Tomcat配置文件(context.xml/server.xml)中的自定义线程池,确保线程初始化时注入App Engine上下文。

5. 调整Java 17模块化限制

Java 17的模块化系统可能限制App Engine API对线程上下文的反射访问,需在启动参数中添加:

--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED

如果是fat jar打包,确保这些JVM参数被正确传递。

内容的提问来源于stack exchange,提问作者Kjell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 23:35:36