今日更新
技术新闻
精彩专题
IBM软件技术专区
微软开发专区
技术文档中心
编程语言
网络通信
网络安全
LINUX/UNIX
软件工程与管理
数据库开发
WEB开发
企业应用与开发
移动开发
资源中心
原创专栏
开放系统世界
人才与培训
技术天地论坛
厂商列表
社区推荐

· 女性身体内部人体受孕..
· 十部顶级的变态与情色..
· 感情放纵让我毁了两个..
· 当我撞见姐姐和男友在..
· 卖淫少女惨遭泄愤民工..
· 偷拍街上的走光mm绝对..
· 百度打击google的广告
· 港娱乐圈与黑社会揭秘
赛迪网>>技术应用>>重点推荐
关键字: c;c++;java
来  源: 开放系统世界——赛迪网
如何在C/C++中调用Java (1)
作者:刘冬 发文时间:2003.02.17
Java跨平台的特性使Java越来越受开发人员的欢迎,但也往往会听到不少的抱怨:用Java开发的图形用户窗口界面每次在启动的时候都会跳出一个控制台窗口,这个控制台窗口让本来非常棒的界面失色不少。怎么能够让通过Java开发的GUI程序不弹出Java的控制台窗口呢?其实现在很多流行的开发环境例如JBuilder、Eclipse都是使用纯Java开发的集成环境。这些集成环境启动的时候并不会打开一个命令窗口,因为它使用了JNI(Java Native Interface)的技术。通过这种技术,开发人员不一定要用命令行来启动Java程序,可以通过编写一个本地GUI程序直接启动Java程序,这样就可避免另外打开一个命令窗口,让开发的Java程序更加专业。

JNI允许运行在虚拟机的Java程序能够与其它语言(例如C和C++)编写的程序或者类库进行相互间的调用。同时JNI提供的一整套的API,允许将Java虚拟机直接嵌入到本地的应用程序中。图1是Sun站点上对JNI的基本结构的描述。



图1 JNI基本结构描述图


本文将介绍如何在C/C++中调用Java方法,并结合可能涉及到的问题介绍整个开发的步骤及可能遇到的难题和解决方法。本文所采用的工具是Sun公司创建的 Java Development Kit (JDK) 版本 1.3.1,以及微软公司的Visual C++ 6开发环境。

环境搭建


为了让本文以下部分的代码能够正常工作,我们必须建立一个完整的开发环境。首先需要下载并安装JDK 1.3.1,其下载地址为“http://java.sun.com”。假设安装路径为C:\JDK。下一步就是设置集成开发环境,通过Visual C++ 6的菜单Tools→Options打开选项对话框如图2。



图2 设置集成开发环境图


将目录C:\JDK\include和C:\JDK\include\win32加入到开发环境的Include Files目录中,同时将C:\JDK\lib目录添加到开发环境的Library Files目录中。这三个目录是JNI定义的一些常量、结构及方法的头文件和库文件。集成开发环境已经设置完毕,同时为了执行程序需要把Java虚拟机所用到的动态链接库所在的目录C:\JDK \jre\bin\classic设置到系统的Path环境变量中。这里需要提出的是,某些开发人员为了方便直接将JRE所用到的DLL文件直接拷贝到系统目录下。这样做是不行的,将导致初始化Java虚拟机环境失败(返回值-1),原因是Java虚拟机是以相对路径来寻找所用到的库文件和其它一些相关文件的。至此整个JNI的开发环境设置完毕,为了让此次JNI旅程能够顺利进行,还必须先准备一个Java类。在这个类中将用到Java中几乎所有有代表性的属性及方法,如静态方法与属性、数组、异常抛出与捕捉等。我们定义的Java程序(Demo.java)如下,本文中所有的代码演示都将基于该Java程序,代码如下:

package jni.test;
/**
 * 该类是为了演示JNI如何访问各种对象属性等
 * @author liudong
 */
public class Demo {
 //用于演示如何访问静态的基本类型属性
 public static int COUNT = 8;
 //演示对象型属性
 public String msg;
 private int[] counts;
 public Demo() {
 this("缺省构造函数");
 }
 /**
  * 演示如何访问构造器
  */
 public Demo(String msg) {
  System.out.println("<init>:" + msg);
  this.msg = msg;
  this.counts = null;
 }
 /**
  * 该方法演示如何访问一个访问以及中文字符的处理
  */
 public String getMessage() {
  return msg;
 }
 /**
  * 演示数组对象的访问
  */
 public int[] getCounts() {
  return counts;
 }
 /**
  * 演示如何构造一个数组对象
 */
 public void setCounts(int[] counts) {
  this.counts = counts;
 }
 /**
  * 演示异常的捕捉
 */
 public void throwExcp() throws IllegalAccessException {
  throw new IllegalAccessException("exception occur.");
 }
}


初始化虚拟机


本地代码在调用Java方法之前必须先加载Java虚拟机,而后所有的Java程序都在虚拟机中执行。为了初始化Java虚拟机,JNI提供了一系列的接口函数Invocation API。通过这些API可以很方便地将虚拟机加载到内存中。创建虚拟机可以用函数 jint JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args)。对于这个函数有一点需要注意的是,在JDK 1.1中第三个参数总是指向一个结构JDK1_ 1InitArgs, 这个结构无法完全在所有版本的虚拟机中进行无缝移植。在JDK 1.2中已经使用了一个标准的初始化结构JavaVMInitArgs来替代JDK1_1InitArgs。下面我们分别给出两种不同版本的示例代码。

在JDK 1.1初始化虚拟机:

#include <jni.h>
int main() {
 JNIEnv *env;
 JavaVM *jvm;
 JDK1_1InitArgs vm_args;
 jint res;
 /* IMPORTANT: 版本号设置一定不能漏 */
 vm_args.version = 0x00010001;
 /*获取缺省的虚拟机初始化参数*/
 JNI_GetDefaultJavaVMInitArgs(&vm_args);
 /* 添加自定义的类路径 */
 sprintf(classpath, "%s%c%s",
 vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
 vm_args.classpath = classpath;
 /*设置一些其他的初始化参数*/
 /* 创建虚拟机 */
 res = JNI_CreateJavaVM(&jvm,&env,&vm_args);
 if (res < 0) {
  fprintf(stderr, "Can't create Java VM\n");
  exit(1);
 }
 /*释放虚拟机资源*/
 (*jvm)->DestroyJavaVM(jvm);
}


JDK 1.2初始化虚拟机:

/* invoke2.c */
#include <jni.h>
int main() {
 int res;
 JavaVM *jvm;
 JNIEnv *env;
 JavaVMInitArgs vm_args;
 JavaVMOption options[3];
 vm_args.version=JNI_VERSION_1_2;//这个字段必须设置为该值
 /*设置初始化参数*/
 options[0].optionString = "-Djava.compiler=NONE"; 
 options[1].optionString = "-Djava.class.path=."; 
 options[2].optionString = "-verbose:jni";	//用于跟踪运行时的信息
 /*版本号设置不能漏*/
 vm_args.version = JNI_VERSION_1_2;
 vm_args.nOptions = 3;
 vm_args.options = options;
 vm_args.ignoreUnrecognized = JNI_TRUE;
 res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
 if (res < 0) {
  fprintf(stderr, "Can't create Java VM\n");
  exit(1);
 }   
 (*jvm)->DestroyJavaVM(jvm);
 fprintf(stdout, "Java VM destory.\n");
}


为了保证JNI代码的可移植性,建议使用JDK 1.2的方法来创建虚拟机。JNI_CreateJavaVM函数的第二个参数JNIEnv *env,就是贯穿整个JNI始末的一个参数,因为几乎所有的函数都要求一个参数就是JNIEnv *env。

访问类方法


初始化了Java虚拟机后,就可以开始调用Java的方法。要调用一个Java对象的方法必须经过几个步骤:

1.获取指定对象的类定义(jclass)

有两种途径来获取对象的类定义:第一种是在已知类名的情况下使用FindClass来查找对应的类。但是要注意类名并不同于平时写的Java代码,例如要得到类jni.test.Demo的定义必须调用如下代码:

jclass cls = (*env)->FindClass(env, "jni/test/Demo");	//把点号换成斜杠


然后通过对象直接得到其所对应的类定义:

jclass cls = (*env)-> GetObjectClass(env, obj);
//其中obj是要引用的对象,类型是jobject


2.读取要调用方法的定义(jmethodID)

我们先来看看JNI中获取方法定义的函数:

jmethodID (JNICALL *GetMethodID)(JNIEnv *env, jclass clazz, const char *name, 
const char *sig);
jmethodID (JNICALL *GetStaticMethodID)(JNIEnv *env, jclass class, const char 
*name, const char *sig);


1 2 3 下一页>>



赛迪网推出“IT博客”,花不到一分钟就完成注册
评论】 【推荐】 【 】 【打印】 【关闭

·Linux专区· ·黑客攻防·
· Linux下添加硬盘、分区、格式化任务详解
· FreeBSD服务器的安装与优化之优化篇
· 初学者入门:FreeBSD服务器的安装与优化
· 金企鹅杯两岸四地开源软件大赛圆满结束
· 如何提高Linux系统安全性的十大招数
· 构筑Linux防火墙之为个人用户设置防火墙
· 谁更安全?黑客眼中的防火墙与路由器
· 识破骗局 练就识别QQ活动真伪火眼金睛
· 应用安全大有可为:目的、挑战、总结
· 道高一尺魔高一丈:安全防御的动感魅力
· 警惕网络“内”院起火 积极谋求安内之路
· HHCTRL漏洞被黑客利用 疯狂传播木马
·中国信息化· ·成功案例·
· ERP普及化是饮鸩止渴 精细化才是应用之道
· 赛门铁克第八期《互联网安全威胁报告》解析
· 抢食“数字工商” 国产中间件杀出血路
· 从IBM等操作系统的发展看软件创新的启示
· 服务成就蓝色快车 品牌是怎样炼成的?
· 三大技术应用大会合为一体甲骨文上演三重奏
· 南阳教育城域网 拆掉学校间的“围墙”
· 金算盘助申意美步入信息化快车道
· 不为人知的索尼信息化 谁是幕后英雄?
· InforBus/Q在穗高速路联网收费系统中的应用
· J2EE构建最新金融理念和运作模式的网上银行
· 食品安全令人担心 信息化能否保驾护航
*姓  名: 更多资料 了解方案 认识厂商
*单位名称:
*联系电话:
*电子邮件:
    
◆ 相关文章   ◆ 站内热点推荐
· Eclipse使用入门
· Java图形界面开发:SWT全接触
· EJB最佳实践:实体bean保护
· Servlet/JSP服务器端的重定向
· Nokia推出Linux平台的手机软件开发工具
· 网管员论坛
· 开发者之家
· WLAN无限未来
· 我是如何掉进C#的……
· 中国“人件”非正式调查

   
合作网站: IBM dW中国网站 LinuxAID 软件工程专家网 中国系统分析员 UMLChina MATRIX Mobile2008 JavaResearch 华储网 UML软件工程组织 中国JAVA手机网 JAVA中文站 金山在线 海量科技