【问题标题】:Java Dynammic Class loading inside webapp在 webapp 中加载 Java 动态类
【发布时间】:2016-03-12 17:42:15
【问题描述】:

我做了一个java项目,项目只包含这个类:

package test.processor;

public abstract class Processor {

    public abstract void loadData(String objectId);
    public abstract void processData();
    public abstract void saveData(String objectId);

}

项目导出为 jar 文件(processor.jar)

然后我做了另一个导入processor.jar的项目,并且有一个扩展Processor的类:

package test.process;

import test.processor.Processor;

public class Process extends Processor{

    @Override
    public void loadData(String objectId) {
        System.out.println("LOAD DATAAAAAAAAAAAA");     
    }

    @Override
    public void processData() {
        System.out.println("PROCESS DATAAAAAAAAAAAA");
    }

    @Override
    public void saveData(String objectId) {
        System.out.println("SAVE DATAAAAAAAAAAAA");
    }

}

此项目也导出为 jar (plugin.jar)。

最后,我编写了一些代码来动态加载插件:

import test.processor.Processor;

public class Test {

    public void testPlugins(){

        Processor plugin = (Processor) loadJar(
                "C:\\Users\\...\\Desktop\\plugin.jar",
                "test.process.Process");
        processor.loadData("dada");

    }

    private Object loadJar(String jar, String className){

        File jarFile = new File(jar);
        Object instance = null;
        try {
            URL jarpath = jarFile.toURI().toURL();
            String jarUrl = "jar:" + jarpath + "!/";
            URL urls[] = { new URL(jarUrl) };
            URLClassLoader child = new URLClassLoader(urls);
            Class classToLoad = Class.forName(nomeClasse, true, child);
            instance = classToLoad.newInstance();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return instance;

    }


} 

如果我在 main 方法中运行该代码,它可以正常工作,一旦我尝试在服务器中运行它,加载类时就会出现问题,我得到一个 ClassNotFoundException(处理器)。 我尝试将jar放在tomcat/lib、project/WEB-INF/lib中,没有任何改变。

知道我做错了什么吗?

【问题讨论】:

    标签: java jar classloader urlclassloader


    【解决方案1】:

    我没有按照我想要的方式解决它,但我解决了它:

    首先我尝试手动加载 process.jar:

    private Object loadJars(String processJar, String pluginJar, String className){
    
        File processJarFile = new File(processJar);
        File pluginJarFile = new File(pluginJar);
    
    
        Object instance = null;
        try {
    
            URL processJarPath = processJarFile.toURI().toURL();
            String processJarUrl = "jar:" + processJarPath + "!/";
    
            URL pluginJarPath = pluginJarFile.toURI().toURL();
            String pluginJarUrl = "jar:" + pluginJarPath + "!/";
    
    
            URL urls[] = { new URL(processJarUrl), new URL(pluginJarUrl) };
            URLClassLoader child = new URLClassLoader(urls);
            Class classToLoad = Class.forName(nomeClasse, true, child);
            instance = classToLoad.newInstance();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return instance;
    
    }
    

    正确加载 Process 类,问题发生在 testPlugins 方法中,一旦它尝试强制转换为处理器(ClassCastException,无法将进程转换为处理器):

    public void testPlugins(){
    
        Processor plugin = (Processor) loadJars("C:\\Users\\...\\Desktop\\processor.jar",
                "C:\\Users\\...\\Desktop\\plugin.jar",
                "test.process.Process");
        processor.loadData("dada");
    
    }
    

    仍然需要阅读很多关于类加载的内容,但我想问题是它无法识别从 C:\Users\...\Desktop\processor.jar 加载的处理器与从webapp 上下文或它“忘记”进程扩展处理器。

    我很着急所以没时间研究,解决问题我用反射调用了方法:

    public void modifiedTestPlugins(){
    
        Object plugin = loadJar("C:\\Users\\...\\Desktop\\processor.jar",
                "C:\\Users\\...\\Desktop\\plugin.jar",
                "test.process.Process");
    
        try {
            Method processData = findMethod(obj.getClass(), "processData");
    
            //here I invoke the processData method, it prints: PROCESS DATAAAAAAAAAAAA
            loadData.invoke(processData, new Object[]{});
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    }
    
    private static Method findMethod(Class clazz, String methodName) throws Exception {
        Method[] methods = clazz.getMethods();
        for (int i = 0; i < methods.length; i++) {
            if (methods[i].getName().equals(methodName))
                return methods[i];
        }
        return null;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 2012-10-10
      • 1970-01-01
      • 2014-11-16
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多