【问题标题】:Cast from super class with dynamic class load JAR使用动态类加载 JAR 从超类转换
【发布时间】:2012-02-05 11:37:27
【问题描述】:

我在这个组织有一些课程

--> : Inherit 

TwittEntititesNetwork --> TwitterGephiStreamer

TwittGrapher          --> TwitterGephiStreamer

TwitterGephiStreamer is Abstract 
TwitterGephiStreamer have a method : myMethod()

Directory
    ./myApp.jar
    ./NetworkLogicDirectory/TwittGrapher.jar
    ./NetworkLogicDirectory/TwittEntititesNetwork.jar

我使用此代码动态加载子类(在另一个 .jar 文件中)

public static TwitterGephiStreamer LoadNetworkLogicJar() throws Exception
    {
        File dir = new File(NetworkLogicDirectory);
        URL[] urls = new URL[dir.listFiles().length];
        for(int i = 0;i < dir.listFiles().length;i++)
        {
            File s = dir.listFiles()[i];
            String url  = "file:///"+s.getAbsolutePath();
            urls[i] = new URL(url);

        }
        ClassLoader = new URLClassLoader(urls);

        if(defaultProps.containsKey("NetworkLogic") &&  !defaultProps.getProperty("NetworkLogic").isEmpty())
        {
            Class<?> networkLogicClassLoader = ClassLoader.loadClass("org.naoyun.gephistream.networklogic."+defaultProps.getProperty("NetworkLogic"));
            Object object = networkLogicClassLoader.newInstance();



            return (TwitterGephiStreamer) object;
        }
        else
        {
            throw new Exception("blabalbalbal ");
        }
    }

所以它必须返回一个 TwitterGephiStreamer,我可以将它用作普通类,并且我可以正常使用 myMethod()。

当我在 eclispe 上运行时,它运行良好,我没有任何错误。

当我将我的应用导出为可运行的 .jar (myApp.jar) 时,它会抛出这个错误:

java.lang.ClassCastException: org.naoyun.gephistream.networklogic.TwittEntitiesNetwork cannot be cast to org.naoyun.gephistream.TwitterGephiStreamer
        at org.naoyun.utils.ConfigurationTools.LoadNetworkLogicJar(ConfigurationTools.java:62)
        at org.naoyun.TwitterStreamer.<init>(TwitterStreamer.java:34)
        at org.naoyun.TwitterStreamer.main(TwitterStreamer.java:26)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)

所以,我不知道如何解决这个问题。我的代码是否令人毛骨悚然,但 Eclispe 可以即时处理它,还是有其他我没有更新的东西?

感谢您的宝贵时间!

【问题讨论】:

  • 为什么要这样创建新实例?
  • 好吧,如果其他人创建了一个继承自 TwitterGephiStreamer 的类,他只需将一个带有他的类的 jar 放在正确的目录中并说他想使用他的类。
  • 你确定eclipse和你导出的jar使用的是同一个生成的.class吗?
  • 您的代码绝对令人毛骨悚然。创建自己的类加载器是非常高级的用法,除非你有非常令人信服的理由,否则不推荐。
  • @jenaiz,好吧,我想是的,我只是用 eclipse 创建了可运行的 Jar(我尝试使用清理项目等等......)

标签: java class inheritance casting jar


【解决方案1】:

您的动态类路径中可能不止一次包含 org.naoyun.gephistream.TwitterGephiStreamer。加载子类时,它会加载与之前加载的副本冲突的 TwitterGephiStreamer 副本。

由于 TwittGrapher.jar 和 TwittEntititesNetwork.jar 依赖于相同的核心类/接口(即 TwitterGephiStreamer),我建议将这些类型放在单独的实用程序 jar 中。这应该有助于消除类路径上的任何重复类型并提供干净的 jar 依赖树:

           myApp
          /     \
TwittGrapher  TwittEntitiesNetwork
        \         /
         TwittUtil

【讨论】:

    【解决方案2】:

    您不应该使用 Eclipse 来构建您的可执行 jar,而是手动创建一个,例如使用 Ant 构建脚本。

    当 Eclipse 构建一个可执行的 jar 包时,它会将所有内容打包到一个整洁的包中,通过它自己的类加载器加载依赖的 jar,该类加载器可以在堆栈跟踪中看到的“jarinjarloader”包中找到。当这个类加载器不是 Eclipse 构建的“omni-jar”的一部分时,它无法找到您的外部 jar。

    我过去曾使用URLClassLoader 成功完成您想做的事情:在运行时加载外部 jar。这是一个关于 SO 的问题,解释了如何使用它: Is it possible to “add” to classpath dynamically in java?

    本教程应该有助于使用 Ant 构建可执行 jar: Build an executable jar file by referencing your dependencies

    这个Ant tutorial 与此类似,并展示了如何使用 Eclipse 来完成它,尽管它没有在清单中设置依赖关系。您需要为核心应用程序类执行此操作,而不是在运行时加载任何外部 jar。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 2014-12-29
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      • 2020-06-08
      • 1970-01-01
      相关资源
      最近更新 更多