您的位置:首页 > 编程语言 > C语言/C++

vs2013 C/C++创建Java虚拟机执行Class字节码

2017-01-17 10:28 267 查看
         在看到《The Java™ Native Interface》回调接口这一章时,突然觉得Google创造出Android系统实在是一件很自然的事情。并且觉得其中的技术演进、跨度其实很缓慢并且是很小的。Java虚拟机的概念从其一诞生就一直延续到今天,虚拟机也是Java最核心最本质的东西。Java Applet在目前看来虽然是一个很老旧、很过时的东西,但是它所展现出来的价值确实十分巨大的。这意味着我们可以在大部分的平台上创建Java虚拟机,然后通过Java虚拟机来执行Java二进制字节码。按照这个思路,我们在Linux内核启动之后,就创建出一个虚拟机,然后在该虚拟机上执行我们的Java应用程序代码,这就是Android的雏形。这样看来,觉得国内与国外其实最大的差距并不是所谓的创新能力不足,而真正的原因其实应该是基础科学缺乏研究与积累。

     虽然书中原理讲的比较清楚,但是要运行起这样一个实例来还是比较困难。下面我们就讲一下相应的步骤(一些设置需要参考前面文章):

1.Eclipse中创建JNI_HelloWorld工程

   文件组织形式及结构如下:





实现代码如下(HelloWorld.java):

package com.worthcloud;

public class HelloWorld {

public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Hello World");
}

}
2. vs2013创建一个空解决方案,然后在方案中添加一个win32控制台工程
    建立好后,注意调整为x64版本,配置好jni.h等头文件的引用目录,lib库的引用目录(注:这里我们将C:\Program Files\Java\jdk1.8.0_31\lib目录下的jvm.lib拷贝到我们工程中,用户也可以不用拷贝,只需要链接时能找到该文件即可)

3. 编写C++程序代码,创建虚拟机执行上面的HelloWorld.main程序代码

// JNI_HelloWorld.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <jni.h>

#define PATH_SEPARATOR ";" /*define it to be ':' on solaris*/
#define USER_CLASSPATH "..\\..\\bin" /*where HelloWorld.class is*/

#define HELLOWORLD_CLASS_NAME "com/worthcloud/HelloWorld"

int _tmain(int argc, _TCHAR* argv[])
{
JNIEnv *env = NULL;
JavaVM *jvm = NULL;
jint res = 0;
jclass cls;
jmethodID methodID;
jstring jstr;
jclass stringCls;
jobjectArray args;

#if defined(JNI_VERSION_1_4) || defined(JNI_
4000
VERSION_1_6) || defined(JNI_VERSION_1_8)
JavaVMInitArgs vm_args;
JavaVMOption options[1];

options[0].optionString = "-Djava.class.path="USER_CLASSPATH;
vm_args.version = JNI_VERSION_1_4;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;

/*Create the Java VM*/
res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);

#elif defined (JNI_VERSION_1_2)
JavaVMInitArgs vm_args;
JavaVMOption options[1];

options[0].optionString = "-Djava.class.path="USER_CLASSPATH;
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;

/*Create the Java VM*/
res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
#else
/*current may not support*/
JDK1_1InitArgs vm_args;
char classpath[1024];
vm_args.version = 0x00010001;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
/* Append USER_CLASSPATH to the default system class path */
sprintf(classpath, "%s%c%s",
vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
vm_args.classpath = classpath;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
#endif

if (res < 0)
{
fprintf(stderr, "Can't Create Java VM\n");
return -1;
}

cls = env->FindClass(HELLOWORLD_CLASS_NAME);
if (cls == NULL)
{
res = -2;
goto destroy;
}

methodID = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
if (methodID == NULL)
{
res = -3;
goto destroy;
}

jstr = env->NewStringUTF("from C++");
if (jstr == NULL)
{
res = -4;
goto destroy;
}

stringCls = env->FindClass("java/lang/String");
if (stringCls == NULL)
{
res = -5;
goto destroy;
}

args = env->NewObjectArray(1, stringCls, jstr);
if (args == NULL)
{
res = -6;
goto destroy;
}

env->CallStaticVoidMethod(cls, methodID, args);

destroy:
if (env->ExceptionOccurred())
{
env->ExceptionDescribe();
}
jvm->DestroyJavaVM();

if (res < 0)
{
printf("failure:%d\n", res);
}
return res;
}

4:编译链接
        这里编译、链接不会出什么问题,但是在执行时就是会报告找不到依赖库jvm.dll的情况,你将C:\Program Files\Java\jdk1.8.0_31\jre\bin\server目录下的jvm.dll拷贝到你工程下的任何一个目录,都提示找不到。这需要用如下的方法进行设置:

在PATH环境变量中添加如下两项:

C:\Program Files\Java\jdk1.8.0_31\jre\bin

C:\Program Files\Java\jdk1.8.0_31\jre\bin\server

设置好后cmd查看一下,并重启vs2013:



5:执行

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