我正在进行的项目非常庞大。在尝试为这个春季项目进行加载时间编织时,我被指示使用spring-instrument javaagent以及aspectjweaver javaagent。但是,我注意到使用aspectjweaver代理时,我的发布时间增加了4-6倍。我还可以看到来自ContextOverridingClassLoader的4-6次相同的编织消息。
如果我删除了aspectjweaver但是只使用spring-instrument,我注意到我的启动时间显着减少,每个连接点只有一条编织消息来自AppClassLoader。
唯一的问题是某些特定的类没有被编织(我发现这是由于在类加载器加载错误类之前尚未加载spring应用程序上下文,因为spring是实现编织的机制)。我通过创建自定义javaagent找到了我自己的解决方案,该javaagent能够以与spring-instrument相同的方式进行编织,只有它在premain中而不是在应用程序上下文加载时才这样做。它现在在合理的时间内编织所有类。
但是,我不愿意走这条骇人听闻的道路,因为我只能假设这两个特工的设计原因是这样。
我想知道是否有其他人看到过与aspectjweaver javaagent类似的问题,如果有人可能知道为什么那个代理与使用spring-instrument相比这么慢。
答案 0 :(得分:0)
如果答案让任何人感兴趣,我已经找到了问题。
Spring使用临时类加载器ContextOverridingClassLoader在将bean实际加载到上下文之前获取有关bean类的元数据。
spring-instrument javaagent(或更确切地说,弹簧框架代码可能使用或不使用spring-instrument javaagent)专门编织由用于加载应用程序上下文的类加载器加载的类。
InstrumentationLoadTimeWeaver内部的代码$ FilteringClassFileTransformer:
if (!this.targetClassLoader.equals(loader)) {
return null;
}
return this.targetTransformer.transform(
loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
另一方面,aspectjweaver没有这样的过滤机制,因此甚至会编织由spring的临时ContextOverridingClassLoader加载的类。幸运的是,aspectjweaver有一个基本上没有文档的系统属性(或者至少我无法找到任何关于此的文档),名为aj.weaving.loadersToSkip。通过将其设置为:
-Daj.weaving.loadersToSkip=org.springframework.context.support.ContextTypeMatchClassLoader$ContextOverridingClassLoader
我能够为该类加载器跳过编织,并极大地加快了应用程序上下文的加载速度。
顺便说一句,我发现spring-instrument和aspectjweaver最终都使用ClassPreProcessorAgentAdapter来编写类,因此可能没有必要同时使用这两个代理(aspectjweaver将编织弹簧类的超集) -instrument will)。但是,根据您的配置,应用程序可能会在启动时抱怨丢失的代理程序,因此您可能会将其包括在内(以一些额外的不必要开销为代价)。