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,緣由亦如。
相關文章
相關標籤/搜索