Tomee中的@Asynchronous方法产生内存泄漏日志错误

@Asynchronous method in Tomee generates memory leak log error

我在单例 class 中有一个 @Asynchronous 方法,它从 EJB 调用以在系统中进行一些清理。

@Singleton
public class AuthTokenCleanup {

    @Inject
    AuthTokenService tokenService;

    @Asynchronous
    @Lock(LockType.READ)
    @TransactionAttribute(NOT_SUPPORTED)
    public void scheduleCleanupAuthTokens() {

        try {
            Thread.sleep(5000);
            tokenService.cleanup();
        } catch (InterruptedException ex) {
        }
    }
}

调用单例的代码片段。它在 @Stateless EJB

public boolean authenticate(String username, String password) {

      boolean authenticated = false;

      try{  
        Login login = loginLookup.findByUsername(username);
        authenticated = login.equalPassword(password);
      } finally {
        tokenCleanup.scheduleCleanupAuthTokens(); //token cleanup happens here
      }

      return authenticated;
}

取消部署应用程序大约需要 20-30 秒。 我在 catalina 日志文件中看到以下错误

SEVERE: The web application [/MyApp] 
appears to have started a thread named [@Asynchronous MyApp-1.0-SNAPSHOT - 3] 
but has failed to stop it. This is very likely to create a memory leak.

我是 运行 Apache-tomee-1.7.1-jaxrs 上的应用程序。 我的 pom.xml 配置

的片段
    <properties>
        <tomee.version>1.7.1</tomee.version>
        <openejb.javaee.api>6.0-6</openejb.javaee.api>        
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.2</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
          <compilerArguments>
               <endorseddirs>${endorsed.dir}</endorseddirs>
          </compilerArguments>
        </configuration>
    </plugin>

当我删除 @Asynchronous 调用时,取消部署需要 1-3 秒,并且日志文件中没有错误。

在使用 @Asynchronous 方法调用时,TomEE 是否会出现预期的行为和错误?如果不是,我做错了什么?

EJB 规范要求 EJB 组件不 directly access thread primitives(包括 Thread.sleep())。这是因为容器需要处理线程管理,如果应用程序正在执行此操作,将无法有效地执行此操作。

如果清理任务需要在单例中定期完成,您是否考虑过使用scheduled job,使用@Schedule注解?这将更适合 EJB 模型,也意味着您不会为每个处理的调用启动一个新的异步请求,因此它也可能会更好地扩展。