当前位置:首页 » 编程语言 » cjni调用java

cjni调用java

发布时间: 2023-08-30 10:50:04

⑴ 请教JNI编程中C调用java实现中NullPointerException问题

java 与 C++ 两种编程语言,它们之间的相互调用:
1、java 调用C++编写的dll,可使用JNI 或 Jawin 开源项目(推荐第二种方法)。
2、C++ 调用java 的变量、方法,通过JNI (Java Native Interface)与java类交互。

----操作步骤(只总结第二个)-----
(1) vc6.0编译C++程序,开发环境设置:工具--》选项--》工具,工具标签下:选择“include files”,加入头文件目录:C:\Program Files\Java\jdk1.5.0\include 和 C:\Program Files\Java\jdk1.5.0\include\win32 ;选择“Libary files"下,加入LIB目录:C:\Program Files\Java\jdk1.5.0\lib 。会编译成exe文件。
执行程序环境设置: Path环境变量加入:C:\Program Files\Java\jdk1.5.0\jre\bin\client (jvm.dll所在目录),若不加入path会提示,执行时找不到jvm.dll.

(2)GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
//([Ljava/lang/String;)V 是main()签名
在java程序目录下执行:javap -s -p ClassDemo (注:ClassDemo.java 已经编译)
取main 下面的语句 :: Signature: ([Ljava/lang/String;)V

(3)附代码示例:

java程序
import java.io.*;
public class DemoMain{
public static void main(String[] args) throws java.io.IOException, java.lang.NullPointerException
{
System.out.println("This is a test.");
}
}

C++程序:
#ifndef __cplusplus
#define __cplusplus
#endif
#include "jni.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma comment (lib,"C:\\Program Files\\Java\\jdk1.5.0\\lib\\jvm.lib") // 动态调用lib
#pragma warning(disable: 4129) // 关闭 warning, 4129
void main() {
LoadLibrary("C:\\Program Files\\Java\jre1.5.0\\bin\\client\\jvm.dll"); // 动态调用dll
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.classpath=.";
options[2].optionString = "-verbose:jni";
vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); // 创建虚拟机
if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
};
jclass cls = env->FindClass("DemoMain");
if (cls == 0) printf("Sorry, I can't find the class");
fprintf(stdout, "This is invokeSimplified4.\n");
jmethodID get_main_id;
if(cls != NULL)
{
get_main_id =env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
fprintf(stdout, "This is invokeSimplified5.\n");
if(get_main_id != NULL )
{
jclass string = env->FindClass("java/lang/String");
jobjectArray args = env->NewObjectArray(0,string, NULL);
fprintf(stdout, "This is invokeSimplified6.\n");
int i = env->CallIntMethod(cls, get_main_id, args);
fprintf(stdout, i+ "This is invokeSimplified7.\n");
}
}
jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory\n");
}

⑵ jni调用 java和c是同个线程吗

是的,jni调用时, java和c是同个线程。

检测方法:在java和c中分别把当前线程的id输出出来查看。

Java获取线程Id:

Thread.currentThread().getId();

C中获取线程Id:

GetCurrentThreadId();

⑶ 如何在C/C++中调用Java的方法

JNI允许您从本机代码内调用 Java 类方法。
要做到这一点,通常必须使用 Invocation API 在本机代码内创建和初始化一个 JVM。
下列是您可能决定从 C/C++ 代码调用Java 代码的典型情况:
1.希望实现的这部分代码是平台无关的,它将用于跨多种平台使用的功能。
2.需要在本机应用程序中访问用 Java 语言编写的代码或代码库。
3.希望从本机代码利用标准 Java 类库。
从C/C++ 程序调用 Java 代码的四个步骤:
1.编写 Java 代码。
这个步骤包含编写一个或多个 Java 类,这些类实现(或调用其它方法实现)您想要访问的功能。
2.编译 Java 代码。
在能够使用这些 Java 类之前,必须成功地将它们编译成字节码。
3.编写 C/C++ 代码。
这个代码将创建和实例化 JVM,并调用正确的 Java 方法。
4.运行本机 C/C++ 应用程序。
将运行应用程序以查看它是否正常工作。我们还将讨论一些用于处理常见错误的技巧。

⑷ android jni c 怎么调用java中的私有方法

public static String getTime() {
Log.d("CCallJava", "Call From C Java Static Method" +String.valueOf(System.currentTimeMillis()));
return String.valueOf(System.currentTimeMillis());
}

public void sayHello(String msg) {
Log.d("CCallJava", "Call From C Java void Method" +String.valueOf(System.currentTimeMillis()));
}

⑸ C调用java时使用JNI的问题!急。。。。。

M,是其中的一个组成部分,更详细的看下面:

----------------------------------
操作系统装入jvm是通过jdk中java.exe来完成,通过下面4步来完成jvm环境.
1.创建jvm装载环境和配置
2.装载jvm.dll
3.初始化jvm.dll并挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装载并处理class类。

在我们运行和调试java程序的时候,经常会提到一个jvm的概念.jvm是java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间.
首先来说一下jdk这个东西,不管你是初学者还是高手,是j2ee程序员还是j2se程序员,jdk总是在帮我们做一些事情.我们在了解java之前首先大师们会给我们提供说jdk这个东西.它在java整个体系中充当着什么角色呢?我很惊叹sun大师们设计天才,能把一个如此完整的体系结构化的如此完美.jdk在这个体系中充当一个生产加工中心,产生所有的数据输出,是所有指令和战略的执行中心.本身它提供了java的完整方案,可以开发目前java能支持的所有应用和系统程序.这里说一个问题,大家会问,那为什么还有j2me,j2ee这些东西,这两个东西目的很简单,分别用来简化各自领域内的开发和构建过程.jdk除了jvm之外,还有一些核心的API,集成API,用户工具,开发技术,开发工具和API等组成
好了,废话说了那么多,来点于主题相关的东西吧.jvm在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的java运行环境,因此也就虚拟计算机. 操作系统装入jvm是通过jdk中java.exe来完成,通过下面4步来完成jvm环境.
1.创建jvm装载环境和配置
2.装载jvm.dll
3.初始化jvm.dll并挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装载并处理class类。
一.jvm装入环境,jvm提供的方式是操作系统的动态连接文件.既然是文件那就一个装入路径的问题,java是怎么找这个路径的呢?当你在调用java test的时候,操作系统会在path下在你的java.exe程序,java.exe就通过下面一个过程来确定jvm的路径和相关的参数配置了.下面基于windows的实现的分析.
首先查找jre路径,java是通过GetApplicationHome api来获得当前的java.exe绝对路径,c:\j2sdk1.4.2_09\bin\java.exe,那么它会截取到绝对路径c:\j2sdk1.4.2_09\,判断c:\j2sdk1.4.2_09\bin\java.dll文件是否存在,如果存在就把c:\j2sdk1.4.2_09\作为jre路径,如果不存在则判断c:\j2sdk1.4.2_09\jre\bin\java.dll是否存在,如果存在这c:\j2sdk1.4.2_09\jre作为jre路径.如果不存在调用GetPublicJREHome查HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\“当前JRE版本号”\JavaHome的路径为jre路径。
然后装载jvm.cfg文件JRE路径+\lib+\ARCH(CPU构架)+\jvm.cfgARCH(CPU构架)的判断是通过java_md.c中GetArch函数判断的,该函数中windows平台只有两种情况:WIN64的‘ia64’,其他情况都为‘i386’。以我的为例:C:\j2sdk1.4.2_09\jre\lib\i386\jvm.cfg.主要的内容如下:
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
在我们的jdk目录中jre\bin\server和jre\bin\client都有jvm.dll文件存在,而java正是通过jvm.cfg配置文件来管理这些不同版本的jvm.dll的.通过文件我们可以定义目前jdk中支持那些jvm,前面部分(client)是jvm名称,后面是参数,KNOWN表示jvm存在,ALIASED_TO表示给别的jvm取一个别名,WARN表示不存在时找一个jvm替代,ERROR表示不存在抛出异常.在运行java XXX是,java.exe会通过CheckJvmType来检查当前的jvm类型,java可以通过两种参数的方式来指定具体的jvm类型,一种按照jvm.cfg文件中的jvm名称指定,第二种方法是直接指定,它们执行的方法分别是“java -J”、“java -XXaltjvm=”或“java -J-XXaltjvm=”。如果是第一种参数传递方式,CheckJvmType函数会取参数‘-J’后面的jvm名称,然后从已知的jvm配置参数中查找如果找到同名的则去掉该jvm名称前的‘-’直接返回该值;而第二种方法,会直接返回“-XXaltjvm=”或“-J-XXaltjvm=”后面的jvm类型名称;如果在运行java时未指定上面两种方法中的任一一种参数,CheckJvmType会取配置文件中第一个配置中的jvm名称,去掉名称前面的‘-’返回该值。CheckJvmType函数的这个返回值会在下面的函数中汇同jre路径组合成jvm.dll的绝对路径。如果没有指定这会使用jvm.cfg中第一个定义的jvm.可以通过set _JAVA_LAUNCHER_DEBUG=1在控制台上测试.
最后获得jvm.dll的路径,JRE路径+\bin+\jvm类型字符串+\jvm.dll就是jvm的文件路径了,但是如果在调用java程序时用-XXaltjvm=参数指定的路径path,就直接用path+\jvm.dll文件做为jvm.dll的文件路径.
二:装载jvm.dll
通过第一步已经找到了jvm的路径,java通过LoadJavaVM来装入jvm.dll文件.装入工作很简单就是调用windows API函数:
LoadLibrary装载jvm.dll动态连接库.然后把jvm.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。jvm.dll的装载工作宣告完成。
三:初始化jvm,获得本地调用接口,这样就可以在java中调用jvm的函数了.调用InvocationFunctions->CreateJavaVM也就是jvm中JNI_CreateJavaVM方法获得JNIEnv结构的实例.
四:运行java程序.
java程序有两种方式一种是jar包,一种是class. 运行jar,java -jar XXX.jar运行的时候,java.exe调用GetMainClassName函数,该函数先获得JNIEnv实例然后调用java类java.util.jar.JarFileJNIEnv中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用java.c中LoadClass方法装载该主类(使用JNIEnv实例的FindClass)。main函数直接调用java.c中LoadClass方法装载该类。如果是执行class方法。main函数直接调用java.c中LoadClass方法装载该类。

然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中
“public static void main(String[] args)”方法,并判断该方法是否为public方法,然后调用JNIEnv实例的
CallStaticVoidMethod方法调用该java类的main方法。
另外,虚机团上产品团购,超级便宜

⑹ 如何在c++中调用java代码

c语言调用Java,还有Java调用C,都使用到JNI技术,C语言调用需要创建Java虚拟机,可查看函数JNI_CreateJavaVM、DestroyJavaVM的资料,函数声明在jni.h头文件(JDK)中。需注意参数类型转换,两种语言的参数类型和传递有讲究,有多个返回的话,必须传递对象参数进行处理。

⑺ 如何通过JNI在Java中调用C库函数

要在java中调用c语言的库,需要使用Java提供了JNI。
举例说明
在c语言中定义一个 void sayHello()函数(打印Hello World);然后在Java中调用这个函数显示Hello Word.
现在分别从Java和C语言两部分说明:
1. Java 部分
首先定义一个HelloNative,在其中申明sayHello函数,函数要申明为Native 类型的.如下:
public class HelloNative {
public native void sayHello();
}

编译这个类,生成class文件:
javac HelloWorld.java

利用javah生成需要的h文件
javah HelloNative

生成的 h文件大概如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */

#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_sayHello
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

可以看一下上面自动生成的程序,程序include了jni.h,这个头文件在 $JAVA_HOME下的include文件夹下. 还可以发现生成的函数名是在之前的函数名前面加上了Java_HelloNative。
2. C语言部分
根据上面生成的h文件编写相应的代码实现,建立一个 HelloNative.cpp用来实现显示Hello World的函数.如下:

#include <stdio.h>
#include "HelloNative.h"

JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject)
{
printf("Hello World!\n");
}

代码编写完成之后,我们再用gcc编译成库文件,命令如下;
gcc -fPIC -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -shared -o libHelloNative.so HelloNative.cpp

这样就会在当前目录下生成一个libHelloNative.so的库文件.这时需要的库已经生成,在C语言下的工作已经完成了.
接下来需要在Java中编写一个程序测试一下.在程序前,需要将我们的库载入进去.载入的方法是调用Java的 System.loadLibrary("HelloNative");

public class TestNative
{
static {
try {
System.loadLibrary("HelloNative");
}
catch(UnsatisfiedLinkError e) {
System.out.println( "Cannot load hello library:\n " + e.toString() );
}
}
public static void main(String[] args) {
HelloNative test = new HelloNative();
test.sayHello();
}
}

但是再编译后,运行的时候,问题又出现了.
Cannot load hello library:
java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.sayHello()V
at HelloNative.sayHello(Native Method)
at TestNative.main(TestNative.java:13)

载入库失败,但是库明明就是放在当前文件夹下的,怎么会载入失败呢?
用System.getProperty("java.library.path")查看,发现java.library.path中并不u存在当前的目录.主要有以下的几个解决办法:
1) 将生成的库复制到java.library.path有的路径中去,当然这样不是很好
2) 设置环境变量export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ,将当前的目录加入到LD_LIBRARY_PATH中
3) 设置java 的选项,将当前的目录加入到其中 .java -Djava.library.path=. $LD_LIBRARY_PATH
这样之后程序就能够成功的运行了.可以看见显示的"Hello World!"了

热点内容
linuxdateshell 发布:2025-03-14 18:04:13 浏览:983
mysql数据库迁移方案 发布:2025-03-14 18:04:12 浏览:388
如何通过中转服务器访问外网 发布:2025-03-14 18:03:31 浏览:15
linux挂载点与分区 发布:2025-03-14 17:58:10 浏览:318
redmine数据库 发布:2025-03-14 17:46:46 浏览:656
c语言编辑器软件 发布:2025-03-14 17:46:39 浏览:862
java远程服务器文件 发布:2025-03-14 17:40:00 浏览:225
小米手机怎么关闭脚本工具 发布:2025-03-14 17:33:46 浏览:118
我的世界正版服务器怎么导出 发布:2025-03-14 17:23:31 浏览:621
php和aspnet 发布:2025-03-14 17:19:05 浏览:712