NutzCN Logo
问答 自定义classloader加载class报错,请问应该怎么办?
发布于 3119天前 作者 gaohuijue 4929 次浏览 复制 上一个帖子 下一个帖子
标签:
package com.qs.modules;

import javax.servlet.http.HttpServletRequest;

import org.nutz.dao.Dao;
import org.nutz.dao.util.Daos;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.NutConfig;
import org.nutz.mvc.Setup;
@IocBean
public class MainSetup implements Setup {
	@Override
	public void init(NutConfig conf) {
		Ioc ioc = conf.getIoc();
        Dao dao = ioc.get(Dao.class);
        Daos.createTablesInPackage(dao, "com.qs.modules.weixin.bean", false);
        
        Class<?> classZ;
		try {
		//自定义classloader加载一个类,执行这句话就报错了
			classZ = Mvcs.getIoc().get(MyClassLoader.class).findClass("");
			Mvcs.getAtMap().addMethod("/", classZ.getMethod("doRequest", HttpServletRequest.class,String.class));
		} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void destroy(NutConfig conf) {

	}

}
//findClass方法的实现。这个MyLicenseAction.dll其实是编译后的class文件。
String path=Thread.currentThread().getContextClassLoader().getResource("").toString();
		path=path.replace('/', '\\').replace("file:", "").replace("classes\\","").substring(1)+"lib\\MyLicenseAction.dll";
		File f = new File(path);
		InputStream is = null;
		try {
			is = new FileInputStream(f);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		byte[] bs = decrypt(is);
		return super.defineClass("com.qs.modules.license.LicenseAction", bs, 0, bs.length);

我用junit测试的话就正常,不会报错。写在mainsetup中,启动tomcat就会报错。
错误信息如下:

java.lang.LinkageError: loader (instance of  com/qs/modules/MyClassLoader): attempted  duplicate class definition for name: "com/qs/modules/license/LicenseAction"
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
	at com.qs.modules.MyClassLoader.findClass(MyClassLoader.java:35)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
	at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
	at java.lang.Class.getMethod0(Class.java:3018)
	at java.lang.Class.getMethod(Class.java:1784)
	at com.qs.modules.MainSetup.init(MainSetup.java:23)
	at org.nutz.mvc.impl.NutLoading.evalSetup(NutLoading.java:276)
	at org.nutz.mvc.impl.NutLoading.load(NutLoading.java:120)
	at org.nutz.mvc.ActionHandler.<init>(ActionHandler.java:19)
	at org.nutz.mvc.NutFilter._init(NutFilter.java:87)
	at org.nutz.mvc.NutFilter.init(NutFilter.java:65)
	at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:279)
	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:260)
	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:105)
	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4917)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5609)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1574)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1564)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
7 回复

先判断类是否存在,然后再defineClass

@wendal
在super.defineClass之前我class.forname("com/qs/modules/license/LicenseAction")报classnotfound,说明是不存在

"class.forname("com/qs/modules/license/LicenseAction")" 肯定ClassNotFound啊, 任何时候执行都是ClassNotFound, 因为类名不会这样写啊

再说, 也不能用Class.forName判断, 要用你自己定义的classloader, 先执行super.findClass,没有找到的话再defineClass

@wendal
抱歉,我是这样"com.qs.modules.license.LicenseAction"写的,因为我是预先把这个类编译成class然后再读取然后每个字节加1,然后改了名字放到了WEB-INF的lib下,然后我自定义类加载器读取这个文件的。这个类如果我不用自定义类加载器肯定是不会被加载的。

先find再define

@wendal
我junit测试能通过为什么在nutz中不行呢?

@gaohuijue 那是junit里面那代码只执行了一次,只进入了一次,所以没有重复

添加回复
请先登陆
回到顶部