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

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

1.Eclipse中创建JNI_HelloWorld工程

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

vs studio怎么编译java_Java

vs studio怎么编译java_Eclipse + vs2013 JNI_02

实现代码如下(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_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:

vs studio怎么编译java_Eclipse + vs2013 JNI_03


5:执行

vs studio怎么编译java_vs studio怎么编译java_04