【发布时间】:2018-09-13 20:53:45
【问题描述】:
在将我们的 Spring Boot 应用程序从嵌入式码头移动到嵌入式 tomcat 后,我们遇到了与类加载器和 orika 相关的问题。 这里有两个类:
@Getter
@Builder
public class SettingsModel {
public final Boolean useSelfSignUp;
public final Boolean approve;
public final Boolean verifyData;
public final Boolean collectMid;
public final Boolean flowEnabled;
public final String partnerName;
public final String networkType;
public final String upc;
}
和
@Getter
@Setter
public class SettingsDto {
private Boolean useSelfSignUp;
private Boolean approve;
private Boolean verifyData;
private Boolean collectMid;
private String partnerName;
private String networkType;
private Boolean flowEnabled;
private String upc;
}
和映射代码:
private final MapperFacade mapper;
...
mapper.map(settingsDto, SettingsModel.class)
迁移到嵌入式 tomcat 映射后抛出异常
Caused by: java.lang.IllegalAccessError: tried to access method
onboarding.data.models.SettingsModel.<init>(Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V from class onboarding.data.models.SettingsModel_SettingsDto_ObjectFactory1006013014242721698432955$9
我发现 orika 使用具有下一个代码的 JavassistCompilerStrategy
Class<?> compiledClass = byteCodeClass.toClass(Thread.currentThread().getContextClassLoader(), this.getClass().getProtectionDomain());
当我们使用嵌入式码头 Thread.currentThread().getContextClassLoader() - 返回 sun.misc.Launcher$AppClassLoader 并且一切都按预期工作,但是在移动到嵌入式 tomcat 后它返回 TomcatEmbeddedWebappClassLoader 并且映射抛出异常。
看起来两个类加载器在工作 sun.misc.Launcher$AppClassLoader 和 TomcatEmbeddedWebappClassLoader,而这个 tomcat 类加载器在 SettingsModel 中找不到所有具有默认访问修饰符(由 lombok 生成)的 args 构造器。
jar包用于app。
我不确定这个问题是否与 Orika 或 spring boot 有关。
我也发现了类似的问题https://gitter.im/spring-projects/spring-boot/archives/2016/01/15,但不确定是同样的问题还是其他问题,并且无法应用那里提供的修复,因为这些类在 spring boot 2.0.3.RELEASE 版本中不可用。
我尝试对 Orika 使用 EclipseJdtCompilerStrategy 而不是 JavassistCompilerStrategy,但没有帮助
春季启动版本 - 2.0.3.RELEASE
orika 版本 - 1.5.2
【问题讨论】:
-
像这样的类加载器问题很难仅从描述中诊断出来。你能提供一个minimal, complete, and verifiable example吗?
-
@AndyWilkinson 这里是示例项目github.com/AlexSylka/spring-boot-class-loader-issue
-
我发现在这种情况下使用 Lombok 是一个障碍。它使调试变得更加困难,以获得最小的收益。如果我将 Lombok 从示例项目中剥离出来,则不再出现问题。您能否通过删除 Lombok 并将其替换为仍会触发问题的必要代码来使示例更简洁?
-
我已经删除了 lombok 并且问题仍然可以重现。如果您将 SettingsModel 构造函数设置为“公共”代码将起作用,但这并不意味着类加载器没有问题。理论上它可以出现在其他地方。
-
@AndyWilkinson 我认为这个问题可能与这个github.com/spring-projects/spring-boot/issues/2308 有关。试图找到一些解决方法。目前我只看到一个:公开构造函数。
标签: java spring-boot classloader embedded-tomcat-8 orika