【问题标题】:DLLs for a dynamic Java program?动态Java程序的DLL?
【发布时间】:2011-01-05 16:14:23
【问题描述】:

我目前正在处理一个 Java 项目,其中我有一组数据,我希望以多种自定义格式输出这些数据。对于每种格式,我都有一个类,它获取原始数据并进行相应的转换。但是,一开始我只实现了其中两种或三种格式,但希望以后可以添加更多格式,而无需对应用程序进行大规模重建。

我的想法是为每个格式类创建一个 DLL,并让我的应用程序将要转换的数据传递给每个格式类。这样,我可以稍后创建一个 DLL 并让我的主应用程序访问它。 (我很乐意听取任何替代方法,因为之前在 C++/C# 中做过这件事的人觉得这是合乎逻辑的解决方案,但它可能不适用于 Java)

我的问题是我完全不知道如何做到这一点 - 在 C++/C# 中,我可以用几行代码编写它,但我不确定它如何与 Java 一起使用。冒着问一个非常模糊的问题的风险,我该怎么做?

非常感谢您的回答,我们将提供饼干和茶。 :)

提前致谢, M

编辑:对不起,只是补充一下:我也不确定如何创建 DLL,该项目必须在 Java 中才能首先读取。谢谢。 :)

【问题讨论】:

    标签: java dll


    【解决方案1】:

    似乎需要某种插件架构,而不是使用 DLL 本身。

    除非必要,否则我不建议使用 DLL 的一个原因是,将 Java 代码与本机代码链接将需要使用 Java Native Interface (JNI),这可能比纯 Java 解决方案需要更多的努力。

    一种相对简单的方法是使用 Java 的 reflection 功能。

    根据所提供的信息,我可能会遵循以下思路:

    1. 为输出格式定义一个接口。
    2. 创建一个实现接口的 Java 类。
    3. classpath 获取课程。
    4. 使用反射动态加载类。 (使用Class.newInstance方法可以从ClassLoader加载的class文件中实例化对象。)

    通过这些步骤,可以实现一个简单的插件,在需要支持新格式时不需要完全重建。


    第 1 步:定义接口

    假设我们最终得到如下界面:

    public interface Outputter {
      public void write(Data d);
    }
    

    第 2 步:制作实现类

    然后,我们将创建一个实现类。

    public class TextOutputter {
      public void write(Data d) {
        // ... output data to text
      }
    }
    

    然后,编译上述内容,我们将得到一个名为 TextOutputter.classclass 文件。

    第 3 步:使类从类路径可用

    在运行主应用程序时,我们需要在classpath 中包含上述TextOutputter.class。通常,我们会告诉 JVM 一个位置列表来考虑作为类路径,其中应该包括上面的 class 文件。

    完成后,我们应该能够使用反射加载上述类。

    第 4 步:使用反射动态加载类

    现在,当我们真正想要加载上述类时,我们会执行以下操作:

    // Note: We load the class by specifying the fully-qualified class name!
    Class<?> clazz = Class.forName("TextOutputter");
    
    // Then, we instantiate the class.
    // Note that the following method will call the no-argument constructor.
    Outputter outputter = clazz.newInstance();      
    
    // Now, we can give data to the TextOutputter object that we loaded dynamically.
    outputter.write(...);
    

    Class.forName 方法用于尝试从默认的ClassLoader 中查找TextOutputter 类。一旦我们将类作为Class 表示形式获得,我们就可以实例化该类的一个对象。

    可以使用Class.newInstance 方法来实例化对象。如果应该使用无参数构造函数以外的其他东西,则必须获取该类的 Constructor,然后从那里实例化对象。

    然后将通过反射实例化的对象放入Outputter 变量中,因此可以在TextOutputter 上调用write 方法。

    添加更多格式需要上述过程,但只需更改全限定类名称(例如,String,FQCN 为 java.lang.String)即可加载不同的类。


    简而言之,这就是动态加载class 文件并在您的应用程序中使用它所需要的。

    (顺便说一句,我并没有真正编译上面的代码,所以这里和那里可能会有一些错误,但我希望我能说明它所需要的过程。)

    【讨论】:

    • 是的,除非您想使用需要 JNI 和动态本机库的类(用于高性能或将 POJO 用作包装器的特定外部库),否则此方法有效。由于您无法使用标准类加载器重新加载 DLL 绑定类,因此在这种情况下您需要对其进行子类化。
    • 附加说明,在较新版本的 java 中,您可以使用服务提供者机制 (java.util.ServiceProvider) 来标准化从插件 jar 中加载插件实现。
    • @dweeves:你不需要继承类加载器。您只需要使用单独的类加载器并在要卸载 dll 时将其丢弃。
    • 非常感谢所有发帖的人,看看不同的方法是非常有趣和有用的。我真的要感谢 Coobird 您花时间开发这个答案,我想我不能要求比您提供的更多的东西,我真的很感激。明天我进入办公室时我会尝试一下,希望这会奏效。再次感谢,我欠你一品脱。
    • @Myn,很高兴我能帮上忙 :)
    【解决方案2】:

    我做过这样的事情。 我创建了一个基于 POJO 的开放式 Java 插件架构,它甚至可以在更新插件类的过程中重新加载。 JNI 是处理本机代码的接口。 唯一的技术部分是重写一个能够在运行时动态重新加载 DLL 的类加载器。 但是,如果您只进行“离线”更新,则不需要此类操作。

    【讨论】:

      【解决方案3】:

      您可以随时使用 System.loadLibrary() 加载新的 DLL。但是,您可能需要加载一个 java 类才能绑定到它。

      您可能会发现使用 OSGi 容器很有帮助,因为它支持加载和卸载模块(包括共享库)

      我建议将 karaf 与 iPOJO 一起使用,但还有很多其他的。

      【讨论】:

        【解决方案4】:

        如果你想编写本地代码(编译成 DLL)在 java 中使用,你想看看Java Native Interface (JNI)

        更新你可以使用System.loadLibrary(String libName)(如果你知道库名并设置了库路径)或System.load(String filename)(库文件名)在java中加载库(DLL)。

        【讨论】:

          【解决方案5】:

          我认为你可以忽略 JNI 路径。我的印象是您使用 dll 一词是因为缺少更好的词,您实际上并不需要 dll。

          您可以在 Java 中做同样的事情,但是您需要将过滤器放在 jar 文件中而不是 dll 中。

          1. 为要实现的文件格式过滤器定义一个接口
          2. 将每个实现放入 jar 中的特定文件夹(如“过滤器”)中
          3. 在应用程序的某一时刻,遍历文件夹,为 jar 生成类加载器
          4. 使用反射查找接口的所有实现,并为每个实现创建一个类
          5. 调用方法来完成它们的工作

          基本上就是这样。

          【讨论】:

            【解决方案6】:

            Java SE 6 引入了 ServiceLoader 类: http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html

            如果您想要适当的模块化方法,请考虑 NetBeans 平台(尤其是桌面应用程序)或 OSGi。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-11-24
              • 1970-01-01
              • 1970-01-01
              • 2010-10-10
              • 1970-01-01
              相关资源
              最近更新 更多