您的位置:首页 > 编程语言 > Java开发

本地方法(JNI)——使用调用API

2016-02-02 10:42 495 查看

【0】README

1) 本文文字描述+source code 均转自 core java volume 2 , 旨在理解 本地方法(JNI)——使用调用API 的基础知识 ;

2) for source code, please visit : https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter12/chapter12_9

【1】本地方法(JNI)——使用调用API

(干货——能够把java 虚拟机嵌入到C 或 C++ 程序中)

1)problem+solution:

1.1)problem:你有一个C 或 C++程序, 并且想要调用一些java 代码;

1.2)solution:调用API(Invocation API) 使你能够把 java 虚拟机嵌入到 C 或者 C++ 程序中。

2)下面是你 初始化虚拟机的代码: (干货——初始化虚拟机的代码, 有点新鲜)

JavaVMOption options[1];
JavaVMInnitArgs vm_args;
JavaVM *jvm; //干货——虚拟机指针jvm
JNIEnv *env;

options[0].optionString = "-Djava.class.path=.";

memset(&vm_args, 0, sizeof(vm_args));
vm_args_version=JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.optoins = options;

JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args); //初始化虚拟机


对以上代码的分析(Analysis):

A1) 对 JNI_CreateJavaVM 的调用将创建虚拟机, 并且使指针jvm 指向虚拟机, 使指针env 指向执行环境; (干货——创建java虚拟机)

A2) 可以给虚拟机提供任意数目的选项, 这只需要增加选项数组的大小和 vm_args.nOptions 的值;

A3)看个荔枝: options[1].optionString = “-Djava.compiler=NONE”; // 这可以钝化即时编译器; (干货——钝化即时编译器)

Warning) 当你陷入麻烦导致程序崩溃, 从而不能初始化 JVM 或者不能装载你的类时, 请打开 JNI 调试模式。 设置一个选项如下: (干货——虚拟机打开 JNI 调试模式)

options[i].optionString=”-verbose:jni”; // 你将会看到一系列说明JVM 初始化进程的消息;

3)只有在调用 Invocation API 中的其他函数时, 才需要 jvm 指针。 目前,只有四个这样的函数,最重要的一个是 终止虚拟机的函数:

(*jvm)->DestoryJavaVM(jvm);

4)看个荔枝: 下面的C程序设置了 虚拟机, 然后调用了 Welcome 类的 main 方法。 (仅供了解啦, 我也不懂他的源代码,呵呵。)

/**
@version 1.20 2007-10-26
@author Cay Horstmann
*/

#include <jni.h>
#include <stdlib.h>

#ifdef _WINDOWS

#include <windows.h>
static HINSTANCE loadJVMLibrary(void);
typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **, void **, JavaVMInitArgs *);

#endif

int main()
{
JavaVMOption options[2];
JavaVMInitArgs vm_args;
JavaVM *jvm;
JNIEnv *env;
long status;

jclass class_Welcome;
jclass class_String;
jobjectArray args;
jmethodID id_main;

#ifdef _WINDOWS
HINSTANCE hjvmlib;
CreateJavaVM_t createJavaVM;
#endif

options[0].optionString = "-Djava.class.path=.";

memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;

#ifdef _WINDOWS
hjvmlib = loadJVMLibrary();
createJavaVM = (CreateJavaVM_t) GetProcAddress(hjvmlib, "JNI_CreateJavaVM");
status = (*createJavaVM)(&jvm, (void **) &env, &vm_args);
#else
status = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
#endif

if (status == JNI_ERR)
{
fprintf(stderr, "Error creating VM\n");
return 1;
}

class_Welcome = (*env)->FindClass(env, "Welcome");
id_main = (*env)->GetStaticMethodID(env, class_Welcome, "main", "([Ljava/lang/String;)V");

class_String = (*env)->FindClass(env, "java/lang/String");
args = (*env)->NewObjectArray(env, 0, class_String, NULL);
(*env)->CallStaticVoidMethod(env, class_Welcome, id_main, args);

(*jvm)->DestroyJavaVM(jvm);

return 0;
}

#ifdef _WINDOWS

static int GetStringFromRegistry(HKEY key, const char *name, char *buf, jint bufsize)
{
DWORD type, size;

return RegQueryValueEx(key, name, 0, &type, 0, &size) == 0
&& type == REG_SZ
&& size < (unsigned int) bufsize
&& RegQueryValueEx(key, name, 0, 0, buf, &size) == 0;
}

static void GetPublicJREHome(char *buf, jint bufsize)
{
HKEY key, subkey;
char version[MAX_PATH];

/* Find the current version of the JRE */
char *JRE_KEY = "Software\\JavaSoft\\Java Runtime Environment";
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, JRE_KEY, 0, KEY_READ, &key) != 0)
{
fprintf(stderr, "Error opening registry key '%s'\n", JRE_KEY);
exit(1);
}

if (!GetStringFromRegistry(key, "CurrentVersion", version, sizeof(version)))
{
fprintf(stderr, "Failed reading value of registry key:\n\t%s\\CurrentVersion\n", JRE_KEY);
RegCloseKey(key);
exit(1);
}

/* Find directory where the current version is installed. */
if (RegOpenKeyEx(key, version, 0, KEY_READ, &subkey) != 0)
{
fprintf(stderr, "Error opening registry key '%s\\%s'\n", JRE_KEY, version);
RegCloseKey(key);
exit(1);
}

if (!GetStringFromRegistry(subkey, "JavaHome", buf, bufsize))
{
fprintf(stderr, "Failed reading value of registry key:\n\t%s\\%s\\JavaHome\n",
JRE_KEY, version);
RegCloseKey(key);
RegCloseKey(subkey);
exit(1);
}

RegCloseKey(key);
RegCloseKey(subkey);
}

static HINSTANCE loadJVMLibrary(void)
{
HINSTANCE h1, h2;
char msvcdll[MAX_PATH];
char javadll[MAX_PATH];
GetPublicJREHome(msvcdll, MAX_PATH);
strcpy(javadll, msvcdll);
strncat(msvcdll, "\\bin\\msvcr71.dll", MAX_PATH - strlen(msvcdll));
msvcdll[MAX_PATH - 1] = '\0';
strncat(javadll, "\\bin\\client\\jvm.dll", MAX_PATH - strlen(javadll));
javadll[MAX_PATH - 1] = '\0';

h1 = LoadLibrary(msvcdll);
if (h1 == NULL)
{
fprintf(stderr, "Can't load library msvcr71.dll\n");
exit(1);
}

h2 = LoadLibrary(javadll);
if (h2 == NULL)
{
fprintf(stderr, "Can't load library jvm.dll\n");
exit(1);
}
return h2;
}

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java jni