C++ 跨语言调用 Java  

  Java JDK 提供了 JNI 接口供 C/C++ 程序调用 Java 编译后的类与方法,主要依赖于头文件(jni.h) 和 动态库(jvm.so/jvm.dll),由于 JNI 包含了丰富的接口映射和跨语言的数据通信,非常复杂(坑 深不见底),所以这里只对一个测试程序进行简单的描述。

  最开始测试的时候选择了 Window7 64 的环境,安装的 Java JDK 也是64位的,但是我们都知道 VS 编译的程序默认情况下都是32位程序,所以我在 LoadLibrary(“jvm.dll”)的时候总是失败,所以就放弃了 Windows 环境下的测试(懒得去编译64的程序),最终我使用了 CentOS7 64 完成了测试,并且测试的 Java 版本是 1.7(系统自带openjdk)。

测试的 Java 代码如下所示。

 public class MyTest {
private static int magic_counter = 777; public static void callback() {
System.out.println("Hello world in java from cplusplus");
System.out.print("Magic number: ");
System.out.println(magic_counter);
}
}

  编写完 Java 测试程序之后,使用命令:javac MyTest.java 对 Java 类进行编译,并生成相应的 MyTest.class 文件,这个文件所在的位置非常重要,这关系到我们的 C++ JNI 程序能否找到这个文件,因为我们在 C++ JNI 程序中指定了 "-Djava.class.path=." 就是C++程序运行的当前目录,所有这里我们需要把 MyTest.class 文件拷贝到 C++ 程序的运行目录中。

  此外由于 JNI 函数需要将调用对象的 Signature ID 传入,所以我们还需要知道你所有使用对象的 Signature。通过命令: javap -s -p MyTest.class 命令可以获取后所有函数与变量的 Signature。如下图所示。

  在编译程序之前,需要了解你机器上的 Java 版本,及 jni.h 和 jvm.so 所在的位置,方便程序编译时能够找到相应的 Java 依赖,这里我使用了 CMake 来辅助编译,相应的 CMakeList.txt 如下所示。

cmake_minimum_required(VERSION 3.5)
project(testjni) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") include_directories(
#/opt/program/jdk1..0_121/include/linux
#/opt/program/jdk1..0_121/include
/usr/lib/jvm/java-1.7.-openjdk-1.7.0.111-2.6.7.2.el7_2.x86_64/include/linux
/usr/lib/jvm/java-1.7.-openjdk-1.7.0.111-2.6.7.2.el7_2.x86_64/include )
link_directories(
#/opt/program/jdk1..0_121/jre/lib/amd64/server
/usr/lib/jvm/java-1.7.-openjdk-1.7.0.111-2.6.7.2.el7_2.x86_64/jre/lib/amd64/server/
) set(SOURCE_FILES main.cpp)
add_executable(testjni ${SOURCE_FILES}) target_link_libraries(
testjni
jvm
)

  下面是 C++ JNI 程序的简单示例,如下所示。

#include <iostream>
#include <jni.h>
#include <memory.h> int main()
{
char opt1[] = "-Djava.compiler=NONE"; /** 暂时不知道啥意思,网上抄来的 */
char opt2[] = "-Djava.class.path=."; /** 指定Java类编译后.class文件所在的目录 */
char opt3[] = "-verbose:NONE"; /** 暂时不知道啥意思,网上抄来的 */ JavaVMOption options[];
options[].optionString = opt1; options[].extraInfo = NULL;
options[].optionString = opt2; options[].extraInfo = NULL;
options[].optionString = opt3; options[].extraInfo = NULL; JavaVMInitArgs jargv;
jargv.version = JNI_VERSION_1_6; /** JDK JNI VERSION*/
jargv.nOptions = ;
jargv.options = options;
jargv.ignoreUnrecognized = JNI_TRUE; JavaVM* jvm = NULL;
JNIEnv* jenv = NULL;
jint res = JNI_CreateJavaVM( &jvm, (void**)&jenv, &jargv );
if ( != res )
return ; jclass jc = jenv->FindClass( "MyTest" );
if ( NULL == jc )
return ; jmethodID jmid = jenv->GetStaticMethodID( jc, "callback", "()V" );
if ( NULL == jmid )
return ; jenv->CallStaticVoidMethod( jc, jmid ); /** 在网上没有找到任何关于空间相关 JavaVM 和 JNIEnv 资源释放的描述 */
std::cout << "Hello, World!" << std::endl;
return ;
}

  最终输出的结果与预期的一致,就到这里,在这么深的坑里,祝大家好运哦。

C++ 跨语言调用 Java的更多相关文章

  1. Atitit java c# php c++ js跨语言调用matlab实现边缘检测等功能attilax总结

    Atitit java c# php c++ js跨语言调用matlab实现边缘检测等功能attilax总结 1.1. 边缘检测的基本方法Canny最常用了1 1.2. 编写matlab边缘检测代码, ...

  2. Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用

    目录: 一.什么是Thrift? 1) Thrift内部框架一瞥 2) 支持的数据传输格式.数据传输方式和服务模型 3) Thrift IDL 二.Thrift的官方网站在哪里? 三.在哪里下载?需要 ...

  3. Java跨语言调用,使用JNA访问Java外部接口

    1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即 ...

  4. 使用thrift进行跨语言调用(php c# java)

    使用thrift进行跨语言调用(php c# java)   1:前言 实际上本文说的是跨进程的异构语言调用,举个简单的例子就是利用PHP写的代码去调C#或是java写的服务端.其实除了本文提供的办法 ...

  5. Golang通过Thrift框架完美实现跨语言调用

    每种语言都有自己最擅长的领域,Golang 最适合的领域就是服务器端程序. 做为服务器端程序,需要考虑性能同时也要考虑与各种语言之间方便的通讯.采用http协议简单,但性能不高.采用TCP通讯,则需要 ...

  6. vs2019 Com组件初探-简单的COM编写以及实现跨语言调用

    前提条件 1.掌握C++基础语法 2.平台安装 vs2019 3.本地平台为 windows 10 1909 X64 4.了解vbs基础语法 本次目标 1.掌握Com组件的概念及原理 2.编写一个简单 ...

  7. 跨语言调用Hangfire定时作业服务

    跨语言调用Hangfire定时作业服务 背景 Hangfire允许您以非常简单但可靠的方式执行后台定时任务的工作.内置对任务的可视化操作.非常方便. 但令人遗憾的是普遍都是业务代码和hagnfire服 ...

  8. 03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写

     1  案例场景,通过C语言回调Java的代码,案例的最终界面: 2  案例的代码结构如下: 3 编写DataProvider的代码: package com.example.ndkcallbac ...

  9. CLS(公共语言规范)的CLSCompliant(跨语言调用)

    .net的一个很重要的特性就是跨语言的编程,用C#写的dll可以在VB.net里调用,例如:用C#写的一个类,编译到dll中,然后在VB.net中调用: using System;namespace  ...

随机推荐

  1. Java字节码浅析(二)

    英文原文链接,译文链接,原文作者:James Bloom,译者:有孚 条件语句 像if-else, switch这样的流程控制的条件语句,是通过用一条指令来进行两个值的比较,然后根据结果跳转到另一条字 ...

  2. .Net 读取配置文件 xml

    直接解析XML文件 1.System.Xml.Linq命名空间下提供可以使用linq查询的类,使用linq to xml读取也很方便. 2.还可以使用System.Xml.Serialization类 ...

  3. Java(1)JDK安装

    1.安装JDK开发环境 下载网站:http://www.oracle.com/ 开始安装JDK: 修改安装目录如下: 确定之后,单击"下一步". 注:当提示安装JRE时,可以选择不 ...

  4. Hadoop数据类型

    hadoop包装了java的基本数据类型使他们实现以上的接口而且给予实现细节,这些类都实现了WritableComparable接口,能够在不同的hadoop节点之间毫无障碍的传输了.

  5. MySQL安装指南(转)

    MySQL安装指南   安装MySQL sudo apt-get install mysql-server 这个应该很简单了,而且我觉得大家在安装方面也没什么太大问题,所以也就不多说了,下面我们来讲讲 ...

  6. 正确开启Mockjs的三种姿势:入门参考(一)

    一.文章初衷 阅读本文章需要注意以下几点: 文章不主要介绍Mockjs的使用语法 文章暂不涉及Mockjs的第三方封装框架 文章会结合以往做过上线项目的方式总结 想主要介绍如何使用Mockjs,是因为 ...

  7. centos 7.4 u盘安装

    因为核心视频服务要运行在centos环境下,so,配了台牛逼的thinkstation(其实有点浪费) 1:u盘制作 下载centos7.4 的iso镜像文件CentOS-7-x86_64-DVD-1 ...

  8. 『PyTorch × TensorFlow』第十七弹_ResNet快速实现

    『TensorFlow』读书笔记_ResNet_V2 对比之前的复杂版本,这次的torch实现其实简单了不少,不过这和上面的代码实现逻辑过于复杂也有关系. 一.PyTorch实现 # Author : ...

  9. js创建对象的三种方法

    1.使用对象初始化器:{} var person = {....} 2 var person=new object() function person(参数) { this.参数=... } var ...

  10. Mac OS 下安装nvm

    关于安装: curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh 安装完成后关闭终端,重新打开终端输 ...