当前位置: 首页 > 面试题库 >

AspectJ:尝试使用外部aop.xml文件时出现ClassLoading问题

阮俊弼
2023-03-14
问题内容

我米试图所以我删除了外部化的aop.xml中配置aop.xmlMETA-INF,并使其在通过系统管理者服务器进行手动配置提供。

当我尝试使用以下外部aop.xml时

-Dorg.aspectj.weaver.loadtime.configuration="file:D:\Workspace\tomcat7\shared\lib\aop.xml"

java.lang.RuntimeException: Cannot register non aspect: aspectclass....主要是因为当时还没有加载aj casse
AppClassLoader。下次它尝试从中注册各方面时WebAppClassLoader(在加载所有类之后),它可以正常工作,但是我仍然从第一次尝试注册时记录到异常。

ClassLoaderWeavingAdaptor.java第307行捕获并记录了异常。

当调用以下行时:success = registerAspects(weaver,loader,definitions);

捕获并记录了异常。

    try {
        registerOptions(weaver, loader, definitions);
        registerAspectExclude(weaver, loader, definitions);
        registerAspectInclude(weaver, loader, definitions);
        success = registerAspects(weaver, loader, definitions);
        registerIncludeExclude(weaver, loader, definitions);
        registerDump(weaver, loader, definitions);
    } catch (Exception ex) {
        trace.error("register definition failed", ex);
        success = false;
        warn("register definition failed", (ex instanceof AbortException) ? null : ex);
    }

在BcelWeaver.java的以下行中恰好引发了异常

if (type.isAspect()) {
      ......
} else {
        // FIXME AV - better warning upon no such aspect from aop.xml
        RuntimeException ex = new RuntimeException("Cannot register non aspect: " + type.getName() + " , " + aspectName);
        if (trace.isTraceEnabled()) {
            trace.exit("addLibraryAspect", ex);
        }
        throw ex;
    }

当方面尚未加载时,如何防止classLoader将错误记录到控制台。我正在考虑注释从源文件记录异常的行,并重新构建Aspectjweaver
jar文件,但是我在寻找一种更好的解决方案而不修改Aspectj源。


问题答案:

我不确定是否有解决您问题的简便方法。正如我说过的,我以前从未与AspectJ合作过,但我相信这是织布人的不当行为。

问题描述:
在引导过程中,代理会尝试申请其他编织不仅对WebAppClassLoader,但是对整体的类加载器链(一旦每一个classloader)即:sun.misc.Launcher$AppClassLoadersun.misc.Launcher$ExtClassLoaderorg.apache.catalina.loader.StandardClassLoader(tomcat的的类加载器)。当您使用该META- INF/aop.xml方法时,由于“配置文件不可用”,它会禁用上述类加载器的编织(如果启用verbose模式,您可以在控制台中看到这些消息)。使用文件配置方法时,
链中的所有类加载器都可以 使用配置。由于它确实找到了配置文件,因此代理会解析定义,因此不会找到方面的类并显示错误。

奇怪的是,如配置文档中所述,如果您使用WeavingURLClassLoader加载时间编织方法,
…它还允许用户通过类加载器显式限制可以编织哪些类”

。因此,这实际上是类加载器方法可以具有的功能(!),而代理程序方法则没有。(很遗憾,我无法使用此方法)

好消息 (好消息 ):
好消息是,您可以轻松创建自己的代理,而忽略上述类加载器的编织。坏消息是,仅限制按类加载器进行编织是不够的,因为如果在同一服务器上有其他应用程序,则Tomcat仍将使用WebAppClassLoader加载它们,因此您仍会收到这些应用程序的错误消息。(在这种情况下,也许您可​​以扩展下面的类来过滤包/类)。

在下面可以找到修改后的代理的两个类。要使用它们,您需要执行以下操作:

  • 解压缩aspectjweaver.jar到文件夹
  • 在“ org/aspectj/weaver/loadtime创建一个新文件夹filter以匹配程序包名称”下,在编译它们之后将两个新类放在其中。
  • 编辑META-INF/MANIFEST.MF文件并更改行

Premain-Class: org.aspectj.weaver.loadtime.Agent
Premain-Class: org.aspectj.weaver.loadtime.filter.FilterAgent

  • 重新打包,您就可以准备好新的代理了。

  • 启动JVM时,您现在可以传递一个新的系统属性,该属性带有一个用逗号分隔的类加载器列表,您想忽略它们-Dorg.aspectj.weaver.loadtime.filter=sun.misc.Launcher$AppClassLoader,sun.misc.Launcher$ExtClassLoader,org.apache.catalina.loader.StandardClassLoader(即,我已经设置CATALINA_OPTS好了)。

这些类是原始代理的类Agent和的修改后的副本ClassPreProcessorAgentAdapter。我添加的唯一代码是解析上述系统属性(如果存在)并忽略对我们不感兴趣的类加载器的调用的部分。

使用后果自负:)希望对您有所帮助

package org.aspectj.weaver.loadtime.filter;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;

public class FilterAgent {

    private static Instrumentation s_instrumentation;

    // Use our own version of ClassFileTransformer that would filter out selected classloaders 
    private static ClassFileTransformer s_transformer = new ClassPreprocessorFilteredAdapter();

    /**
     * JSR-163 preMain Agent entry method
     *
     * @param options
     * @param instrumentation
     */
    public static void premain(String options, Instrumentation instrumentation) {
        /* Handle duplicate agents */
        if (s_instrumentation != null) {
            return;
        }
        s_instrumentation = instrumentation;
        s_instrumentation.addTransformer(s_transformer);
    }

    public static Instrumentation getInstrumentation() {
        if (s_instrumentation == null) {
            throw new UnsupportedOperationException("Java 5 was not started with preMain -javaagent for AspectJ");
        }
        return s_instrumentation;
    }
}
//-----------------------------------------------------------------------------------
package org.aspectj.weaver.loadtime.filter;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.weaver.loadtime.Aj;
import org.aspectj.weaver.loadtime.ClassPreProcessor;


public class ClassPreprocessorFilteredAdapter implements ClassFileTransformer {

    /**
     * Concrete preprocessor.
     */
    private static ClassPreProcessor s_preProcessor;

    private static Map<String, String> ignoredClassloaderNames = new HashMap<String, String>();

    static {
        try {
            s_preProcessor = new Aj();
            s_preProcessor.initialize();


            String ignoredLoaders = System.getProperty("org.aspectj.weaver.loadtime.filter", "");
            if (ignoredLoaders.length() > 0) {
                String[] loaders = ignoredLoaders.split(",");

                for (String s : loaders) {
                    s = s.trim();
                    ignoredClassloaderNames.put(s, s);
                    System.out.println("---> Will filtered out classloader: " + s);
                }
            }

        } catch (Exception e) {
            throw new ExceptionInInitializerError("could not initialize JSR163 preprocessor due to: " + e.toString());
        }
    }

    /**
     * Invokes the weaver to modify some set of input bytes.
     * 
     * @param loader the defining class loader
     * @param className the name of class being loaded
     * @param classBeingRedefined is set when hotswap is being attempted
     * @param protectionDomain the protection domain for the class being loaded
     * @param bytes the incoming bytes (before weaving)
     * @return the woven bytes
     */
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
        if (classBeingRedefined != null) {
            System.err.println("INFO: (Enh120375):  AspectJ attempting reweave of '" + className + "'");
        }

        String loaderName = loader.getClass().getName();
        if (shouldIgnoreClassLoader(loaderName)) {
            return bytes;
        }
        return s_preProcessor.preProcess(className, bytes, loader, protectionDomain);
    }

    private boolean shouldIgnoreClassLoader(String loaderName) {
        boolean result = false;
        String ignoredLoader = ignoredClassloaderNames.get(loaderName);
        if (ignoredLoader != null) {
            result = true;    // if the loader name exists in the map we will ignore weaving
        }
        return result;
    }
}


 类似资料:
  • 问题内容: 我在运行Java项目时遇到问题。 它使用maven编译,最终得到.jar文件。我今天决定,我将使用log4j代替wimple System.out进行日志记录…在此更改之前,它工作正常 这是我的运行方式 SRV_ADDR指向我的service.jar(带有Launcher类) SRV_LIBS指向log4j-1.2.16.jar 我加了“。;” 一开始希望它会有所帮助,因为提到的文件在

  • 因此,我尝试使用coinbase API。我正在尝试一个简单的测试,看看我是否可以让它工作,但我得到了各种作曲家的错误。 目前,我得到意外的t'use'为这个代码: 那么,我的使用声明在错误的地方吗?我在索引函数和类之外尝试过它们。两者产生的结果与此完全不同。 在Keks班之外,我得到了 致命错误:在第15行的/home/content/61/11420661/html/beta/applicat

  • 问题内容: 我有这个: 当我做一个我得到: 在probleme我有是附加在 有人可以帮忙吗,谢谢 问题答案: 尝试以下代码(已修复):

  • 问题内容: 我编写的python程序存在一个小问题,该程序可以从特殊文本文件中提取一些信息。循环(下面的代码)需要执行我的函数,超过500个文件(一个文件列出一个列表),这样我才能构建数据集。 错误:发生的是IOException ,因此由于某种原因python无法访问文件。我已经检查了目录路径名(位置)和文件许可权,它们是正确的(读+写)。有什么想法为什么当文件确实存在且路径名正确时会报告IOE

  • 问题内容: 我正在尝试使用Jackson将一些JSON数据转换为Java对象(精确地说是对象列表),但出现此错误: org.codehaus.jackson.map.JsonMappingException:无法反序列化objectlayerlayer的实例。START_ARRAY令牌之外的详细信息 这是代码: ld 是Json格式的列表,这是让我在jackson教程中感到困惑的部分。这是什么 新

  • 问题内容: 我刚刚开始学习Java,并且只知道少量的代码,但是,这仍然是一个简单的程序。它更多是一个恶作剧程序,但主要只是为了测试我是否可以创建一个jar文件。 这是代码: 我将其保存到名为的文件中,然后使用进行编译 这有效,当我使用运行它时 它也可以正常工作。 因此,然后我尝试创建一个jar文件。我使用命令 而且有效。之后,我双击jar文件,它出现一个错误。 所以我在cmd中运行它 并得到这个错