从 Java 程序中使用 VC++ 组件






4.15/5 (10投票s)
本文介绍如何从 Java 程序访问本地 Windows DLL,以利用 Windows 提供但 Java 无法直接使用的功能。文章介绍了 JNI(Java 本地接口)。
引言
JNI 是我最喜欢的 Java 编程框架;它允许你使用本地创建的代码。例如,如果你想从你的 Java 代码中使用任何 Windows API(即 dll),你可以使用 JNI。
Java 最大的优势在于平台独立性。但是,有时此功能会使 Java 程序与本地平台的集成非常困难。
例如,在我们的项目中,我们使用 MSMQ(Microsoft Messaging Queue)作为排队机制来维护消息(以避免消息丢失),然后再将它们写入数据库。Microsoft 提供了 MSMQ API,这是一个 Windows API。但是我们的程序是用 Java 编写的,Java 无法直接访问此 VC++ API(dll)。因此,我们决定创建一个中间 DLL,它将充当 Java 和 VC++ 之间的桥梁(我们使用了 Java 本地接口或 JNI 技术)。
在继续之前,你应该了解/熟悉一些术语。
- 本地方法:本地方法是在 .java 文件中声明,并在你的本地代码中定义的方法。(对于 Windows,它在 VC++ 中)。
- 静态块:Java 中的静态块是在任何其他事情发生之前执行的代码部分。
让我们开始吧。首先,编写你的 Java 程序,并声明本地方法。以下代码来自示例源码。
public class JNITest
{
static
{
System.loadLibrary("JNITest"); // Loading dll in memory
}
native void showMessage( String str); // Declaring native method
public JNITest()
{
System.out.println( "In the constructor of the Java program" );
}
public static void main( String s[] )
{
JNITest JNT = new JNITest();
JNT.showMessage("Passing string from Java");
}
}
在上面的代码中,我们声明了名为 `showMessage` 的本地方法,并在 `JNITest` 类的对象上调用它。
执行以下步骤:
- 编译代码以生成 .class 文件。
- 在 JDK 文件夹中,你会找到一个名为 **javah** 的实用程序。
- 进入命令提示符并执行 **javah -jni JNITest**
执行上述命令将生成文件 *JNITest.h*。此 .h 文件包含在我们的 Java 代码中声明的本地方法的 VC++ 等效名称。
创建 JNI DLL
我们已经完成了一半。
现在在 Visual Studio(或任何其他 win32 IDE)中创建一个简单的 dll 项目,并将上面的 .h 文件添加到项目中。
将 JRE\INCLUDE 文件夹的路径添加到你的 **includes** 中,以获取包含文件 *jni.h*。
现在你将以略微不同的方式找到在 .java 文件中声明的方法的名称。
在上述情况下,你将得到:
JNIEXPORT void JNICALL Java_JNITest_showMessage(JNIEnv *, jobject, jstring);
这里,**第三个参数**是来自 Java 程序的参数。你可以将其转换为本地形式,如下所示:
const char *strS1 = env->GetStringUTFChars( s1, 0);
在这里,你可以将 `strS1` 用作 C++ 字符串。在演示程序中,我使用它在消息框中显示它。`JNIEnv` 有许多方法可以将各种类型的数据从 Java 转换为 C++。
使用后必须释放字符串,这不是自动的。JNI 活动被认为是 JVM 的外部活动,因此它不会抛出任何可以在 Java 代码中捕获的异常。如果你在离开函数之前忘记释放字符串,这可能会导致你的 JVM 崩溃。
你可以使用函数 `ReleaseStringUTFChars` 释放字符串。
env->ReleaseStringUTFChars( s1, strS1);
整个代码如下所示:
JNIEXPORT void JNICALL Java_JNITest_showMessage(
JNIEnv * env, jobject job, jstring str )
{
const char *strMsgPtr = env->GetStringUTFChars( str , 0);
//Converting string to C++ character pointer
MessageBox( 0, strMsgPtr,"Message box from VC++ ", 0 );
//Using the string
env->ReleaseStringUTFChars( str, strMsgPtr);
// Releasing the string ( character pointer )
}
现在你可以自由地使用 Windows(或 VC++)组件——你现在可以访问任何 Windows API。
构建 dll 并将其放置在你的 Java 程序的文件夹中(包含你的 .class 文件的文件夹)。
现在运行你的 Java 程序。
注意:如果出现 *UnsatisfiedLinkError*,请检查你的方法签名(原型)。它必须与 .h 文件中提供的一致。
使用 JNI,你可以从 Java 程序访问 Windows 提供的各种功能。