代码之家  ›  专栏  ›  技术社区  ›  Andrey Adamovich

方面扫描过多的类和方法缓存会填满内存

  •  5
  • Andrey Adamovich  · 技术社区  · 14 年前

    我们也有一些注释驱动的方面类,我们应用于web服务类。在开头,poincut表达式如下所示:

    @Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..))")
      public void methodsToBeLogged() {
      }
    

    并且通过配置中的条目在服务上启用了AOP。

    OutOfMemoryException 在我们的服务器上。在进行了一些分析和分析之后,似乎内存被AspectJExpressionPointcut类实例保存的缓存占用。

    每个实例的缓存大约为5 MBs。由于我们有3个方面和30个服务,它导致了90个实例,总共持有450MBs的数据。

    在检查高速缓存的内容之后,我们意识到它包含了在战争中存在的所有类的Java反射方法实例,即使那些不是My.PcAg.Services业务包的一部分。在修改了point cut表达式之后 within 条款:

    @Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..)) && 
    within(my.package.service.business..*)")
      public void methodsToBeLogged() {
      }
    

    内存使用率又降到了正常水平。所有AspectJExpressionPointcut实例总共占用不到1MB。

    有人能解释为什么吗?为什么第一个切点表达式是不够的?为什么缓存 AspectJExpressionPointcut 不共享?

    1 回复  |  直到 14 年前
        1
  •  9
  •   Jakub Bochenski    9 年前

    AspectJExpressionPointcut使用了一个缓存(shadowMatchCache),它加快了根据pointcut表达式决定是否应将AOP应用于某个方法调用的速度。这个缓存可能会消耗大量内存。

    另外,在提供特定bean的所有方法以查看是否存在匹配的切入点表达式之前,Spring首先检查bean类是否可以 可能匹配 快速的 根据使用内部切入点的AspectJ开发人员的说法,结果是更明确的no recommend to never use a standalone kind of pointcuts (execution, call, get, set), but combine these with within

    但是,无法共享shadowMatchCache,因为它包含每个切入点表达式匹配或不匹配的结果。

    但至少你可以限制缓存的内容。我还认为,一旦applicationContext启动,Spring可能会通过不保留整个缓存来改进这一点。F、 当一个新的bean在applicationContext已经启动之后被动态添加到applicationContext中时,他们可能会丢弃所有不匹配的内容,代价是重新执行一些匹配。

    AspectJExpressionPointcut类中另一个可能占用内存的地方是pointCutParser。此解析器可能在applicationContext中的所有aspectjexpressionpointcut之间共享。在吉拉的罚单上抢劫 SPR-7678