如果您对AspectJ:尝试使用外部aop.xml文件时出现ClassLoading问题和请尝试使用外部适配器为这台计算机添加蓝牙功能感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解Aspect
如果您对AspectJ:尝试使用外部aop.xml文件时出现ClassLoading问题和请尝试使用外部适配器为这台计算机添加蓝牙功能感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解AspectJ:尝试使用外部aop.xml文件时出现ClassLoading问题的各种细节,并对请尝试使用外部适配器为这台计算机添加蓝牙功能进行深入的分析,此外还有关于Class.forName () 和 ClassLoader.loadClass () 的区别?、Class.forName和ClassLoader.loadClass区别、classloader 加载 class 文件时 会将 class 文件缓冲起来,问如果再加载一遍会将以前的缓存覆盖掉吗、ClassLoader.loadClass() throws java.lang.ClassNotFoundException的实用技巧。
本文目录一览:- AspectJ:尝试使用外部aop.xml文件时出现ClassLoading问题(请尝试使用外部适配器为这台计算机添加蓝牙功能)
- Class.forName () 和 ClassLoader.loadClass () 的区别?
- Class.forName和ClassLoader.loadClass区别
- classloader 加载 class 文件时 会将 class 文件缓冲起来,问如果再加载一遍会将以前的缓存覆盖掉吗
- ClassLoader.loadClass() throws java.lang.ClassNotFoundException
AspectJ:尝试使用外部aop.xml文件时出现ClassLoading问题(请尝试使用外部适配器为这台计算机添加蓝牙功能)
我米试图所以我删除了外部化的aop.xml中配置aop.xml
的META-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 casseAppClassLoader
。下次它尝试从中注册各方面时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源。
答案1
小编典典我不确定是否有解决您问题的简便方法。正如我说过的,我以前从未与AspectJ合作过,但我相信这是织布人的不当行为。
问题描述:
在引导过程中,代理会尝试申请其他编织不仅对WebAppClassLoader
,但是对整体的类加载器链(一旦每一个classloader)即:sun.misc.Launcher$AppClassLoader
,sun.misc.Launcher$ExtClassLoader
,org.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; }}
Class.forName () 和 ClassLoader.loadClass () 的区别?
Class.forName() 和 ClassLoader.loadClass() 的区别 ?
Class.forName() 和 Class.forName().NewInstance() 的区别 ?
Class.forName("xx.xx") 等同于 Class.forName("xx.xx",true,CALLClass.class.getClassLoader()),第二个参数 (boolean) 表示装载类的时候是否初始化该类,即调用类的静态块的语句及初始化静态成员变量。
ClassLoader loader = Thread.currentThread.getContextClassLoader(); // 也可以用 (ClassLoader.getSystemClassLoader())
Class cls = loader.loadClass("xx.xx"); // 这句话没有执行初始化,其实与 Class.forName("xx.xx",false,loader) 是一致的,只是 loader.loadClass("xx.xx") 执行的是更底层的操作。
只有执行 cls.NewInstance() 才能够初始化类,得到该类的一个实例
Class 的装载分了三个阶段,loading,linking 和 initializing,分别定义在 The Java Language Specification 的 12.2,12.3 和 12.4。
Class.forName(className) 实际上是调用 Class.forName(className, true, this.getClass().getClassLoader())。注意第二个参数,是指 Class 被 loading 后是不是必须被初始化。
ClassLoader.loadClass(className) 实际上调用的是 ClassLoader.loadClass(name, false),第二个参数指出 Class 是否被 link。
区别就出来了。Class.forName(className) 装载的 class 已经被初始化,而 ClassLoader.loadClass(className) 装载的 class 还没有被 link。
一般情况下,这两个方法效果一样,都能装载 Class。但如果程序依赖于 Class 是否被初始化,就必须用 Class.forName(name) 了。
例 如,在 JDBC 编程中,常看到这样的用法,Class.forName("com.mysql.jdbc.Driver"),如果换成了 getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行。
为什么呢?打开 com.mysql.jdbc.Driver 的源代码看看,
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can''t register driver!");
}
}
原来,Driver 在 static 块中会注册自己到 java.sql.DriverManager。而 static 块就是在 Class 的初始化中被执行。所以这个地方就只能用 Class.forName(className)。
Class.forName和ClassLoader.loadClass区别
Java中class是如何加载到JVM中的:
1.class加载到JVM中有三个步骤
装载:(loading)找到class对应的字节码文件。
连接:(linking)将对应的字节码文件读入到JVM中。
初始化:(initializing)对class做相应的初始化动作。
2.Java中两种加载class到JVM中的方式
2.1:Class.forName("className");
其实这种方法调运的是:Class.forName(className, true, ClassLoader.getCallerClassLoader())方法
参数一:className,需要加载的类的名称。
参数二:true,是否对class进行初始化(需要initialize)
参数三:classLoader,对应的类加载器
2.2:ClassLoader.laodClass("className");
其实这种方法调运的是:ClassLoader.loadClass(name, false)方法
参数一:name,需要加载的类的名称
参数二:false,这个类加载以后是否需要去连接(不需要linking)
2.3:两种方式的区别
forName("")得到的class是已经初始化完成的
loadClass("")得到的class是还没有连接的
一般情况下,这两个方法效果一样,都能装载Class。
但如果程序依赖于Class是否被初始化,就必须用Class.forName(name)了。
3.举例说明他们各自的使用方法
java使用JDBC连接数据库时候,我们首先需要加载数据库驱动。
Class.forName("com.MySQL.jdbc.Driver");//通过这种方式将驱动注册到驱动管理器上
Connection conn = DriverManager.getConnection("url","userName","password");//通过驱动管理器获得相应的连接
查看com.mysql.jdbc.Driver源码:
public class Driver extends NonRegisteringDriver
implements java.sql.Driver
{
//注意,这里有一个static的代码块,这个代码块将会在class初始化的时候执行
static
{
try
{
//将这个驱动Driver注册到驱动管理器上
DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can''t register driver!");
}
}
}
Class.forName("com.mysql.jdbc.Driver")方法以后,他会进行class的初始化,执行static代码块。
也就是说class初始化以后,就会将驱注册到DriverManageer上,之后才能通过DriverManager去获取相应的连接。
但是要是我们使用ClassLoader.loadClass(com.mysql.jdbc.Driver)的话,不会link,更也不会初始化class。
相应的就不会回将Driver注册到DriverManager上面,所以肯定不能通过DriverManager获取相应的连接。
classloader 加载 class 文件时 会将 class 文件缓冲起来,问如果再加载一遍会将以前的缓存覆盖掉吗
classloader 加载 class 文件时 会将 class 文件缓冲起来,问如果再加载一遍会将以前的缓存覆盖掉吗ClassLoader.loadClass() throws java.lang.ClassNotFoundException
今天写一个 RMI 的应用,气死人了,弄半天,跑到 sun 官网去一看,告诉我是一个 BUG, 我流出了鼻血。
ToWork:
-Dsun.lang.ClassLoader.allowArraySyntax=true
点击打开链接
原文链接: http://blog.csdn.net/chengchanglun/article/details/7441034
我们今天的关于AspectJ:尝试使用外部aop.xml文件时出现ClassLoading问题和请尝试使用外部适配器为这台计算机添加蓝牙功能的分享已经告一段落,感谢您的关注,如果您想了解更多关于Class.forName () 和 ClassLoader.loadClass () 的区别?、Class.forName和ClassLoader.loadClass区别、classloader 加载 class 文件时 会将 class 文件缓冲起来,问如果再加载一遍会将以前的缓存覆盖掉吗、ClassLoader.loadClass() throws java.lang.ClassNotFoundException的相关信息,请在本站查询。
本文标签: