简体   繁体   English

在 JAVA 中运行时从 WAR 外的 JAR 文件动态加载类时出现 ClassCastException 错误?

[英]ClassCastException Error while dynamically loading classes from a JAR file outside WAR at run time in JAVA?

I wanted to dynamically load jar files (and its classes) in my war code.我想在我的战争代码中动态加载 jar 文件(及其类)。

To do this I have written my object factory class as such:为此,我编写了对象工厂类:

import java.io.File;
import java.net.*;

public class ObjectFactory {

    private ClassLoader cl;

    public ObjectFactory(String jarFilePath) {

        try {
            File file= new File(jarFilePath);
            URL url = file.toURL();
            URL[] urls = new URL[]{url};
            cl = new URLClassLoader(urls);
        } catch (Exception e) {
            e.printStackTrace();
        }  


    }


    public <T> T getObject(String id){
        try {
            Class cls = cl.loadClass(id);
            T object =(T)cls.newInstance();

            return object;
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null;
    }

}

I have a Duck interface:我有一个鸭子界面:

public interface Duck {
    public String quack(String arg);
}

And I have created service class to get Ducks I want at runtime:我创建了服务类来在运行时获取我想要的 Ducks:

public class DuckServiceClass {

    public static Duck getDuck(){
        try {
        String jarFilePath="\path\to\my\external_jar.jar"
        ObjectFactory of = new ObjectFactory(jarFilePath);
        Duck d1=of.getObject("implementationOfDuck.RobotDuck");     
        return d1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

My jar has a copy of Duck interface and has various implementation of Duck : for example RobotDuck class:我的 jar 有一个 Duck 接口的副本,并有 Duck 的各种实现:例如 RobotDuck 类:

package implementationOfDuck;
import Duck;

public class RobotDuck implements Duck {

    @Override
    public String quack(String arg) {
        return "Q U A N C K!!!" +arg;
    }

}

This service class works all fine in a main method:这个服务类在主方法中一切正常:

public class WebAppTest {

    public static void main(String[] args) {
        Duck d1 =DuckServiceClass.getDuck();
        System.out.println(d1.getName()+">"+d1.quack("Hello"));
    }

}

But If I refer this ServiceClass method in my jsp page it gives me :但是如果我在我的 jsp 页面中引用这个 ServiceClass 方法,它会给我:

java.lang.ClassCastException: implementationOfDuck.RobotDuck cannot be cast to Duck

My JSP page is :我的 JSP 页面是:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="Duck" %>
<%@ page import="DuckServiceClass" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Duck-O-Gram</title>
</head>
<body>
<%
Duck d1=DuckServiceClass.getDuck();
%>
<h1><%=d1.quack("Hello")%></h1>
</body>
</html>

can any one guide me how to resolve this issue in a webapp ?任何人都可以指导我如何在 webapp 中解决这个问题吗?

As @JimGarrison said, Duck is loaded by webapp class loader and URLClassLoader twice.正如@JimGarrison 所说, Duck由 webapp 类加载器和URLClassLoader加载两次。

Specified the parent class loader in constructor of URLClassLoader could fix the problem.URLClassLoader构造函数中指定父类加载器可以解决这个问题。 cl will search class/resource using parent class loader first, then load class/resource from given URLs. cl将首先使用父类加载器搜索类/资源,然后从给定的 URL 加载类/资源。 Since Duck is already loaded by webapp class loader, Duck.class inside external_jar.jar will not be loaded again.由于Duck已经由 webapp 类加载器加载, Duck.class external_jar.jar 中的Duck.class将不会再次加载。

public ObjectFactory(String jarFilePath) {
    try {
        File file= new File(jarFilePath);
        URL url = file.toURL();
        URL[] urls = new URL[]{url};
        cl = new URLClassLoader(urls, getClass().getClassLoader());
    } catch (Exception e) {
        e.printStackTrace();
    }  
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM