javassist使用中遇到的技术细节记录

1.java -jar 运行jar包时,javassist.ClassPool 报ClassNotFound 在完成基于javassist技术和RequestMappingHandlerMapping实现自定义|动态注册spring mvc HandlerMapping的迭代记录的开发后,部署到线上环境中时,运行提示异常:java

javassist.NotFoundException: cn.yuyizyk.compent.Handler
		at javassist.ClassPool.get(ClassPool.java:422) ~[javassist-3.23.1-GA.jar!/:na]
		at cn.yuyizyk.compent.SrcActionAnalysis.lambda$3(SrcActionAnalysis.java:194) ~[classes!/:0.0.1-SNAPSHOT]

定位错误位置:git

// cn.yuyizyk.compent.SrcActionAnalysis
CtClass handleCtClz = pool.makeClass(Handler.class.getName() + "$" + c.getSimpleName() + "$" + m.getName()+ "R" +
				(new Random().nextInt(1024)),pool.get(Handler.class.getName()));
// javassist.ClassPool :561
/**
 * Searches the class path to obtain the URL of the class file
 * specified by classname.  It is also used to determine whether
 * the class file exists.
 *
 * @param classname     a fully-qualified class name.
 * @return null if the class file could not be found.
 * @see CtClass#getURL()
 */
public URL find(String classname) {
	return source.find(classname);
}
// 而后经过反射定位到  javassist.ClassClassPath 91
/**
 * Obtains the URL of the specified class file.
 *
 * @return null if the class file could not be found.
 */
@Override
public URL find(String classname) {
	String filename = '/' + classname.replace('.', '/') + ".class";
	return thisClass.getResource(filename);// 此处的thisClass : Object.class
}
// 根据java.lang.Class:2265  Object.class.getClassLoader() is null
public java.net.URL getResource(String name) {
	name = resolveName(name);
	ClassLoader cl = getClassLoader0();
		if (cl==null) {
		// A system class.
		return ClassLoader.getSystemResource(name);
	}
	return cl.getResource(name);
}
//java.lang.Class:1226 
public static URL getSystemResource(String name) {
	ClassLoader system = getSystemClassLoader();
		if (system == null) {
		return getBootstrapResource(name);
	}
	return system.getResource(name);
}

所以问题是SystemClassLoader加载cn.yuyizyk.compent.Handler.class 失败。spring

此后,我打印java.class.path 也佐证了这一点:mvc

System.out.println(System.getProperty("java.class.path"));
// TODO main start print
D:\2.git\notes\notes\spring-dynamic-handlerMapping\target\classes;...
// TODO spring jar start print
.\spring-dynamic-handlerMapping-0.0.1-SNAPSHOT.jar

基本能够肯定问题即是SystemClassLoader加载路径不一致致使classNotFound。app

这个问题从何而来? 当把项目打包为jar包运行是,java -jar 会把其余classpath给屏蔽,只使用jar包的classpath.即.\spring-dynamic-handlerMapping-0.0.1-SNAPSHOT.jar,所以没法正确查找class。dom

解决方案 将当前ClassPath 注册到javassist 的ClassPath中便可。ide

ClassPool.getDefault().appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
// TODO 同时注意在生成javassist CtClass -> Class时,加载的classloader不能是SystemClassLoade,缘由亦如。
相关文章
相关标签/搜索