首页 文章

为什么使用aspectjweaver javaagent的加载时间编织这么慢?

提问于
浏览
0

我正在研究的项目相当庞大 . 在尝试为这个 Spring 季项目设计加载时间时,我被指示使用spring-instrument javaagent以及aspectjweaver javaagent . 但是,我注意到在使用aspectjweaver代理时,我的发布时间增加了4-6倍 . 我还可以看到来自ContextOverridingClassLoader的4-6次相同的编织消息 .

但是,如果我删除了aspectjweaver,并且仅使用spring-instrument,我注意到我的启动时间显着减少,每个连接点只有一条编织消息来自AppClassLoader .

唯一的问题是某些特定的类没有被编织(我发现这是由于在类加载器加载错误类之前尚未加载spring应用程序上下文,因为spring是启用编织的机制) . 我通过创建一个自定义javaagent找到了我自己的解决方案,它能够以与spring-instrument相同的方式进行编织,只有它在premain中而不是在应用程序上下文加载时才这样做 . 它现在在合理的时间内编织所有类 .

但是,我不想走这条黑客的道路,因为我只能假设这两个特工的设计方式是有原因的 .

我想知道是否有其他人已经看到了与aspectjweaver javaagent类似的问题,并且如果有人可能知道为什么那个代理与使用spring-instrument相比这么慢 .

1 回答

  • 0

    如果答案让任何人感兴趣,我已经找到了问题 .

    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将要使用的类的超集) . 但是,根据您的配置,应用程序可能会在启动时抱怨丢失的代理程序,因此您可能会将其包括在内(以一些额外的不必要开销为代价) .

相关问题