我正在做的项目相当大。当我试图让这个spring项目的加载时间编织工作时,我被告知要同时使用spring-instrument javaagent和aspectjweaver javaagent。然而,我注意到当使用aspectjweaver代理时,我的启动时间增加了4-6倍。我还可以看到4-6次来自ContextOverridingClassLoader的相同的编织消息。
但是,如果我删除了aspectjweaver,而只使用了spring-instrument,我注意到我的启动时间大大缩短了,因为每个连接点只有一个来自AppClassLoader的编织消息。
唯一的问题是一些特定的类没有被编织(我发现这是因为在类加载器加载错误的类之前,spring应用程序上下文还没有被加载,因为spring是启用编织的机制)。我已经找到了自己的解决方案,通过创建一个自定义的javaagent,它可以像spring-instrument一样实现编织,只是它是在premain中而不是在应用程序上下文加载时进行编织。它现在在合理的时间内编织所有的类。
然而,我不想走这条老路,因为我只能假设这两个代理是这样设计的,这是有原因的。
我想知道是否有其他人看到过aspectjweaver javaagent的类似问题,是否有人可能知道为什么该代理比只使用spring-instrument要慢得多。
发布于 2017-09-05 01:24:29
如果答案让任何人感兴趣,我已经弄明白了问题所在。
Spring使用临时类加载器ContextOverridingClassLoader来获取有关bean类的元数据,然后再将它们实际加载到上下文中。
spring-instrument javaagent (或者更准确地说,spring框架代码,它可以使用也可以不使用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将编织spring-instrument将编织的类的超集)。但是,根据您的配置,应用程序可能会在启动时抱怨缺少代理,因此您也可以包含它(代价是一些额外的不必要的开销)。
https://stackoverflow.com/questions/45994725
复制相似问题