Lambda - ClassNotFoundException

mys*_*cks 8 java lambda spring

这是我的代码的样子,目前还不清楚如何/为什么executorService.submit(work::get)ClassNotFoundException在有问题的匿名类上抛出 a 。它不会一直发生,但是一旦遇到此异常,它似乎无法恢复——随后的请求会遇到相同的异常。任何人都知道可能导致这种情况发生的原因是什么?

编辑:我可以确认对这个方法的所有调用在 VM 会话中都有效,或者没有一个有效 - 它不像某些成功而其他人由于上述异常而失败。

进一步编辑:https : //bugs.openjdk.java.net/browse/JDK-8148560正是我遇到的错误,但由于不可重现和/或记者没有回应,该错误已关闭。不知何故,由 lambda 表达式产生的匿名类型看起来像是在执行程序执行表达式之前被垃圾收集,但显然并非总是如此。使用的 jdk 是openjdk1.8.0_221.

package com.ab.cde.ct.service.impl;

@Service
public class IngestionService {
    @Autowired private TransactionTemplate transactionTemplate;
    @Autowired private AsyncTaskExecutor executorService;

    @Transactional
    public void ingest(Data data) {
        Supplier<Optional<String>> work = () -> transactionTemplate.execute(s -> {
            // actual work on the data object, enclosed in a try/catch/finally
        });
        executorService.submit(work::get); // this is where the exception gets thrown
    }
}
Run Code Online (Sandbox Code Playgroud)

这是异常堆栈跟踪的样子(行号不对应,因为上面的代码只是一个原型):

2019-10-23 19:11:35,267|[http-apr-26001-exec-10]|[B6AC864143092042BBB4A0876BB51EB6.1]|[]|[ERROR] web.error.ErrorServlet  [line:142] org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoClassDefFoundError: com/ab/cde/ct/service/impl/IngestionService$$Lambda$53
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoClassDefFoundError: com/ab/cde/ct/service/impl/IngestionService$$Lambda$53
    at org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1275)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:951)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:867)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:951)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:853)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
Caused by: java.lang.NoClassDefFoundError: com/ab/cde/ct/service/impl/IngestionService$$Lambda$53
    at com.ab.cde.ct.service.impl.IngestionService$$Lambda$53/812375226.get$Lambda(Unknown Source)
    at com.ab.cde.ct.service.impl.IngestionService.ingest(IngestionService.java:264)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at com.sun.proxy.$Proxy252.ingest(Unknown Source)
Caused by: java.lang.ClassNotFoundException: com.ab.cde.ct.service.impl.IngestionService$$Lambda$53
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1364)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1185)
    ... 115 more
Run Code Online (Sandbox Code Playgroud)

Bon*_*ond 5

这是由 lambda 生成的合成方法的情况,它无法找到所需的类(即TransactionCallback),因此出现以下错误

引起:java.lang.NoClassDefFoundError:com/ab/cde/ct/service/impl/IngestionService$$Lambda$53 at com.ab.cde.ct.service.impl.IngestionService$$Lambda$53/812375226.get$Lambda (来源不明)

导致此问题的特定代码是

Supplier<Optional<String>> work = () -> transactionTemplate.execute(s -> {
        // actual work on the data object, enclosed in a try/catch/finally
});
Run Code Online (Sandbox Code Playgroud)

要通过此修改代码如下

TransactionCallback<Optional<String>> callback = transactionStatus -> {
      // your processing goes here  
      return Optional.of("some value"); 
};

Supplier<Optional<String>> work = () -> transactionTemplate.execute(callback);
Run Code Online (Sandbox Code Playgroud)

如果以上仍然不起作用,请使用以下解决方法

Object callback = (TransactionCallback<Optional<String>>)transactionStatus -> {
     // your processing goes here     
     return Optional.of("some value");
};

Supplier<Optional<String>> work = () -> transactionTemplate.execute((TransactionCallback<Optional<String>>)callback);
Run Code Online (Sandbox Code Playgroud)

如果需要更多信息,请在评论中告知。

PS:没有必要使用@Transactionalif transactionTemplate,因为两者本质上都具有相同的目的。

参考:

  1. 此处此处的Lambda 编译
  2. java中的合成方法