在 WebSphere Application Server 中集成 Java EE 应用程序和基于 C 的实现

Java™ 原生接口 (Java Native Interface, JNI) 是一个编程框架,支持在 Java 虚拟机 (JVM) 中运行的 Java 代码调用使用其他语言(比如 C、C++ 和汇编语言)编写的原生应用程序和库,也支持这些应用程序和库调用这些代码。本文将介绍开发人员如何利用此框架将他们在 IBM® WebSphere® Application Server 上部署的 J2EE™ 应用程序与这些 C 库相集成。 本文来自于 IBM WebSphere Developer Technical Journal 中文版

Sharad Chandra, 高级 WebSphere 顾问, IBM

Sharad Chandra 是 IBM 印度软件实验室 IBM PartnerWorld for WebSphere 中的一名高级顾问。他在使用 WebSphere Process Server、WebSphere Lombardi 和 SOA 产品套件开发解决方案方面拥有丰富的经验。在当前的职位上,Sharad 从事过多项涉及可伸缩且高度可用的 WebSphere 基础架构、解决方案开发、迁移、性能调优和故障排除的重要活动。



2012 年 9 月 13 日

简介

IBM® WebSphere® Application Server 是一个兼容 Java® EE 6 的、健壮且高度可用的中间件环境,它提供了一个平台来托管和管理各种不同的企业应用程序。一些用户可能遇到过这样的场景,他们需要将基于 Java 的应用程序与基于 C/C++ 的原生实现相集成。例如,涉及国防、航空、天气预报的应用程序以及其他科学应用程序包含某些算法,这些算法只能使用这些原生语言实现,并且在 Java 中实现起来太复杂、太困难或风险太高。

要将这些基于 C 的实现与 Java 程序相集成,您需要以某种方式在两种编程语言 API 之间建立连接。Java 原生接口 (JNI) 提供了这种衔接方式在 Java 与 C/C++ API 之间交换数据。要实现此解决方案,您需要在 Java 中使用您希望向其他 Java 类公开的方法定义该接口,从该接口的已编译代码生成头文件,然后将此头文件导入到原生的共享库模块中,比如针对 Windows® 的动态链接库 (.dll) 和针对基于 UNIX® 的系统的共享对象 (.so) 库。这些模块可通过多家供应商提供的各种工具来创建。

本文介绍的步骤将简化通过 Java 原生接口 (JNI) 将部署在 WebSphere Application Server 上的基于 Java 的应用程序与基于 C 的实现相集成的过程。掌握本文的内容之后,您就能够为 WebSphere Application Server 创建、配置和调用共享库。

这里包含的信息适用于 IBM WebSphere Application Server V6.1、V7 和 V8,并且假设您熟悉相应的 IBM Rational® 工具。请注意,这里提供的示例非常基本,仅用于演示所涉及的高级开发过程,不包含典型的应用程序开发中通常包含的数据验证或其他优秀实践。


创建原生的共享库

  1. 打开 IBM Integration Designer 并创建一个独立 Java 项目(参见图 1)。
    图 1. 创建独立项目
    图 1. 创建独立项目
  2. 创建一个 Java 类,其中包含您希望与原生访问相关联的方法(参见图 2)。方法声明将依赖于您希望调用的 C 方法的签名。在本例中,假设一个第三方 C API 需要简单类型和一个数据数组(在本例中,为一个双精度数组)。(要调用另一个原生库,您需要通过在头文件实现期间导入它的头文件,将该文件与您的 DLL 相关联。)
    图 2. 创建 Java 类
    图 2. 创建 Java 类
  3. 编译 Java 接口并在从 {APPSERVER_ROOT}/Java/bin 目录中编译生成的 .class 文件上运行 javah 命令,生成各个 C 头文件(参见图 3)。

    <APPSERVER_ROOT>java\bin>javah -o header_file_name.h <JAVA_CLASS_NAME>

    图 3. 生成 C 头文件
    图 3. 生成 C 头文件
  4. 接下来,您需要使用头文件中生成的方法创建一个原生的共享库。可以在 C API 到 C API 调用期间将这个库实现与其他 C 库相集成(参见图 4)。
    图 4. Java 头文件代码
    图 4. Java 头文件代码
  5. 图 4 中所示的头文件代码需要复制到一个共享库项目中,以生成一个 .dll 或 .so 库。可以使用任何 C/C++ 编辑器创建这些共享库。一个 DLL 项目包含一个标头部分(.h 文件,参见图 5)和实现部分(.c 文件,参见图 6),这些部分与其他部分是分开的,具体情况取决于您使用的编辑器。
    图 5. 将 Java 头文件代码复制到 dll 项目标头部分中
    图 5. 将 Java 头文件代码复制到 dll 项目标头部分中
    图 6. 实现部分中的 Java 标头方法的实现
    图 6. 实现部分中的 Java 标头方法的实现
  6. 请注意,jni.h 位于 WebSphere Application Server 中的 Java 运行时 include 目录 {APPSERVER_ROOT}/Java/include 中(参见图 7)。
    图 7. jni.h 在 WebSphere 中的位置
    图 7. jni.h 在 WebSphere 中的位置

请记住,在编译 DLL 模块中的 Java 头文件代码时需要引用 jni.h,您可以将此文件从 {APPSERVER_ROOT}/java/include 目录复制到 C 编辑器位置,将它放在 include 路径中可确保 DLL 的成功编译。当生成 DLL 时,您可以将该文件复制到 WebSphere Application Server 中的合适位置。


在 WebSphere Application Server 中配置原生库

要使用 WebSphere Application Server 配置 DLL,可以将该 DLL 复制到在 {APPSERVER_ROOT} 目录(参见图 8)中创建的一个文件夹中,在 JVM 自定义属性中配置它的路径,只需导航到 Server > ServerTypes > WebSphere Application Server > server1 > Java and Process Management > Process Definition > Java Virtual Machine > Custom Properties(参见图 9)。

图 8. 根目录中用于 DLL 的新文件夹
图 8. 根目录中用于 DLL 的新文件夹
图 9. JVM 自定义属性
图 9. JVM 自定义属性

如果此 JVM 自定义属性未在 WebSphere Application Server 中设置,那么在类加载器尝试加载该 DLL 时,会获得一个异常(参见图 10)。

图 10. 类加载器异常
图 10. 类加载器异常

将 DLL 路径设置为 WebSphere Application Server 中的一个 JVM 自定义属性后,必须重新启动服务器。


使用 WebSphere Application Server 创建 Java EE 解决方案来调用一个原生库

要展示对 DLL 中定义的方法的调用,我们将使用在 WebSphere Application Server 的一个 EAR 文件中部署的一个 servlet。在从任何 Java 类调用原生方法之前,无论它是独立的还是包含在一个 EAR 中,您都需要在一个静态代码块中使用一个 System.loadlibrary 调用加载它。这样,就会在初始类加载期间加载该 DLL(参见图 11)。

图 11. 类加载
图 11. 类加载

要从 Java 类调用原生方法,必须在类路径中拥有用来生成头文件的原生类。在此示例中,此类作为一个 JAR 文件放在 WEB-INF/lib 目录中,以便使 servlet 能够在运行时解析它(参见图 12)。

图 12. 从 Java 类调用 JNI 代码
图 12. 从 Java 类调用 JNI 代码

部署 EAR 后,您必须重新启动服务器,因为 servlet 是在启动时加载的,它会加载 DLL。因为原生库加载在 WebSphere Application Server 原生内存中,所以需要重新启动服务器;否则,您会在调用 servlet 时获得一个异常,指出该库已被另一个类加载器加载。


测试解决方案

在这里,您可以测试两个解决方案,通过将一个简单数据类型传递给原生方法来测试第一个解决方案,通过传递数组来测试另一个解决方案:

  • 简单相加测试

    在此测试中,需要在数据字段中输入整数值,在将这些值相加后,会得到一个结果。

    图 13. 简单相加测试数据输入
    图 13. 简单相加测试数据输入
    图 14. 简单相加测试结果
    图 14. 简单相加测试结果
  • 数组数据测试

    在此测试中,您在 JSP 中输入一个包含 10 个值的数组,然后该 JSP 会通过一个 servlet 调用原生方法,该 servlet 在数组中显示每个字段的双精度值。

    图 15. 双精度值数组测试数据输入
    图 15. 双精度值数组测试数据输入
    图 16. 双精度值数组测试结果
    图 16. 双精度值数组测试结果

结束语

本文提供了一些简单的示例,演示了如何通过 JNI(Java 原生接口),使用 C API 将 WebSphere Application Server 中运行的 Java 代码与基于 C 的实现相集成(通过一个共享动态链接库 (DLL) 在它们之间建立某种连接)。


下载

描述名字大小
代码样例1203_chandra_ProjectData.zip16 KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere, Java technology
ArticleID=834711
ArticleTitle=在 WebSphere Application Server 中集成 Java EE 应用程序和基于 C 的实现
publish-date=09132012