动态 Java 程序的 DLL?

发布于 2024-10-10 04:45:17 字数 477 浏览 0 评论 0原文

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

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

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

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

提前致谢, M

编辑:抱歉,只是补充一下:我也不确定如何创建 DLL,该项目必须使用 Java 来首先读取该 DLL。谢谢。 :)

I'm currently working on a Java project where I have a set of data which I wish to output in several custom formats. I have a class for each format, which takes the raw data and converts it accordingly. However, to begin with I am only implementing two or three of these formats, but wish to allow more formats to be added at a later date without having to do a massive rebuild of the application.

My idea was to create a DLL for each of the format classes, and have my application pass the data to be converted to each of these. This way, I can create a DLL later on and have my main application accessing it. (I would gladly listen to any alternative ways of doing this, as someone who has done this in C++/C# before this felt like the logical solution but it may not be applicable to Java)

My problem is that I have absolutely no idea how to do this - in C++/C# I could write this in a few lines of code but I'm not sure how it works with Java. At the risk of asking a terribly vague question, how can I do this?

Answers are greatly appreciated and cookies and tea will be offered. :)

Thanks in advance,
M

Edit: Sorry, just to add: I am also unsure how to create the DLL, which must be in Java for this project, to be read in the first place. Thanks. :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

单调的奢华 2024-10-17 04:45:17

看起来我们需要的是某种插件架构,而不是使用 DLL 本身。

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

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

根据给出的信息,我可能会遵循以下原则:

  1. 定义输出格式的接口。
  2. 创建一个实现该接口的 Java 类。
  3. 类路径获取该类。
  4. 使用反射动态加载类。 (使用 类.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 步:使类在类路径中可用

运行主应用程序时,我们需要在 类路径。通常,我们会告诉 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 方法。如果应使用除无参构造函数之外的其他构造函数,则必须获取该类的构造函数以继续从那里实例化对象。

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

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


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

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

Rather than using a DLL per se, it seems like what is wanted is a plugin architecture of some sort.

One reason why I wouldn't recommend using a DLL unless it is necessary is that linking Java code with native code will require using the Java Native Interface (JNI) which would probably require more effort than a pure Java solution.

One relatively simple way to do so is to use the reflection capabilities of Java.

From the information given, I would probably go along the lines of the following:

  1. Define an interface for the output format.
  2. Create a Java class implementing the interface.
  3. Have the class available from the classpath.
  4. Dynamically load the class using reflection. (Using the Class.newInstance method can instantiate objects from class files loaded by the ClassLoader.)

With these steps, it would be possible to implement a simplistic plugin which wouldn't require a full rebuild when support for a new format is required.


Step 1: Define the interface

Let's say we end up with an interface like the following:

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

Step 2: Make an implementation class

Then, we'll make an implementation class.

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

Then, compiling the above, we'll end up with a class file called TextOutputter.class.

Step 3: Make the class available from the classpath

When running the main application, we'll need to have the above TextOutputter.class in the classpath. Normally, one would tell the JVM a list of places to consider as the classpath, and that should include the above class file.

Once that is done, we should be able to load the above class using reflection.

Step 4: Dynamically load the class using reflection

Now, when we actually want to load the above class, we'd do something like the following:

// 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(...);

The Class.forName method is used to attempt to find the TextOutputter class from the default ClassLoader. Once we obtain the class as a Class representation, we can then instantiate an object of that class.

Instantiating the object can be performed by using the Class.newInstance method. If something other than the no-argument constructor should be used, the Constructor of the class would have to be obtained proceed to instantiate the object from there.

The object instantiates via reflection is then placed into a Outputter variable, so the write method can be called on the TextOutputter.

Adding more formats would entail the above process, but changing the fully-qualified class name (e.g. for String, the FQCN is java.lang.String) is all that is needed to load up a different class.


In a nutshell, that's what it will take to dynamically load class files and use it from your application.

(Just as a side note, I did not actually compile the above code, so there may be some errors here and there, but I hope I could illustrate the process it will take.)

落墨 2024-10-17 04:45:17

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

I've made such things.
i created an open java based plugin architecture POJO based,that even did reload on the fly of updated plugin classes.
JNI is the interface for dealing with native code.
The only technical part was to rewrite a classloader that enabled DLL reloading dynamically at runtime.
But if you do only make "offline" updates, no such things are needed.

神也荒唐 2024-10-17 04:45:17

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

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

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

You can load a new DLL at any time with System.loadLibrary(). However you may need to load a java class for it to bind to.

You might find using an OSGi container helpful as this supports both load and unloading of modules (including shared libraries)

I would suggest using karaf with iPOJO but there are many others.

黑凤梨 2024-10-17 04:45:17

如果您想编写在 java 中使用的本机代码(编译为 DLL),您需要查看 Java Native接口(JNI)

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

If you want write native codes (compiled to a DLL) to be used in java, you want to look at Java Native Interface (JNI).

Update you can use System.loadLibrary(String libName) (if you know the library name and the library path is set) or System.load(String filename) (library filename) to load library (DLL) in java.

临风闻羌笛 2024-10-17 04:45:17

我认为你可以忽略 JNI 路径。我的印象是您使用 dll 这个术语是因为没有更好的词,您实际上并不需要 dll。

您可以在 Java 中执行相同的操作,但您可以将过滤器放在 jar 文件中而不是 dll 中。

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

基本上就是这样。

I think you can ignore the JNI path. I have the impression you're using the term dll for lack of a better word, you don't really need a dll.

You could do the same thing in Java, but you'd put your filters in jar files instead of dll.

  1. Define an interface for the file format filters to implement
  2. Put each implementation into a jar, in a specific folder (like 'filters')
  3. At one point in the app, iterate over the folder, generate classloader for the jars
  4. Use reflection to find all implementations of your interface, and create a class for each
  5. Call the methods to do their job

That's basically it.

绝不放开 2024-10-17 04:45:17

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

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

Java SE 6 introduces the ServiceLoader class:
http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html

If you want a proper modular approach consider the NetBeans Platform (especially if it is a desktop application) or OSGi.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文